标签:目的 set order 检查 方法 ios ext 思路 idt
●(做codevs1908时,发现测试数据也涵盖了1907,想要一并做了,但因为“技术”不佳,搞了一上午)
●09方格取数问题(codevs1907 方格取数3)


●13星际转移问题(codevs 1908)


●代码(为了AC掉codevs1908,把两份代码怼到一起了):
#include<iostream>
#include<cstdio>
#include<cstring>
#define INF 0x3f3f3f3f
using namespace std;
int n,m,k,yue=1,ear=2,sz=4,ent=2,aim,tot,s,t;
int sps[30][30],cw[30][2],ld[30],ls[30],head[30000],h[30000],q[30000];
int fa[30];
struct edge{
	int to,cap,next;
}e[300000];
bool special_read()
{
	char s[100];
	gets(s);
	int a[4]={0},o=1;
	int len=strlen(s);
	for(int i=0;i<len;i++)
	{
		if(‘0‘<=s[i]&&s[i]<=‘9‘) a[o]=a[o]*10+s[i]-‘0‘;
		else if(a[o]) o++; 
	}
	n=a[1];m=a[2];
	return k=a[3];
}
int read(int &o)
{
	int x=0,f=1; char ch=getchar();
	while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) f=-1;ch=getchar();}
	while(‘0‘<=ch&&ch<=‘9‘) {x=x*10+ch-‘0‘;ch=getchar();}
	o=x*f;
}
void add_edge(int u,int v,int cap)
{
	e[ent]=(edge){v,cap,head[u]};head[u]=ent++;
	e[ent]=(edge){u,0,head[v]};head[v]=ent++;
}
void make_new_edge(int day)
{
	for(int i=3;i<=n+3-1;i++) add_edge(ld[i],++sz,INF),ld[i]=sz;
	for(int i=1;i<=m;i++)
	{
		int t=day%cw[i][1],o=sps[i][t];
		if(o==ear) add_edge(ear,++sz,cw[i][0]),ls[i]=sz;
		else if(o==yue) add_edge(ls[i],yue,cw[i][0]),ls[i]=0;
		else 
		{
			if(ls[i])add_edge(ls[i],ld[o],cw[i][0]);
			ls[i]=ld[o];
		}
	}
}
bool bfs(int s,int t)
{
	memset(h,0,sizeof(h));
	int l=0,r=1;q[1]=s;h[s]=1;
	while(l<r)
	{
		int u=q[++l];
		for(int i=head[u];i;i=e[i].next)
		{
			int v=e[i].to;
			if(h[v]||!e[i].cap) continue;
			h[v]=h[u]+1; q[++r]=v;
		}
	}
	return h[t];
}
int dfs(int u,int res,int t)
{
	if(u==t) return res;
	int flowout=0,f;
	for(int i=head[u];i;i=e[i].next)
	{
		int v=e[i].to;
		if(!e[i].cap||h[v]!=h[u]+1) continue;
		f=dfs(v,min(res,e[i].cap),t);
		e[i].cap-=f; e[i^1].cap+=f;
		flowout+=f; res-=f;
		if(!res) break;
	}
	if(!flowout) h[u]=-1;
	return flowout;
}
int Dinic(int s,int t)
{
	while(bfs(s,t))
	{
		aim+=dfs(s,INF,t);
	}
	return aim;
}
void check_and_add(int a,int b,int c,int d)
{
	c+=a; d+=b;
	if(c==0||c==n+1||d==0||d==m+1) return;
	int u=(a-1)*m+b,v=(c-1)*m+d;
	add_edge(u,v,INF);
}
int find(int x)
{
	if(fa[x]!=x) return fa[x]=find(fa[x]);
	return x;
}
void unio(int x,int y)
{
	int fx=find(x),fy=find(y);
	if(fx!=fy) fa[fy]=fx;
}
void _1908()
{
	for(int i=1;i<=25;i++) fa[i]=i;
	for(int i=1;i<=m;i++)
	{
		read(cw[i][0]);read(cw[i][1]);
		for(int j=0;j<cw[i][1];j++) 
		{
			read(sps[i][j]);
			sps[i][j]+=2;
			if(j) 
			for(int jj=0;jj<j;jj++)
			 unio(sps[i][jj],sps[i][j]);
		}
	}
	if(find(yue)!=find(ear)) printf("0");
	else
	{
		int day=0;
		add_edge(3,ear,k); add_edge(yue,4,INF);
		for(int i=3;i<=n+3-1;i++) ld[i]=++sz;
		for(int i=1;i<=m;i++)
		{
			int o=sps[i][0];
			if(o==ear) add_edge(ear,++sz,cw[i][0]),ls[i]=sz;
			else if(o!=yue) ls[i]=ld[o];
		}
		while(1)
		{
			++day;
			make_new_edge(day);
			if(Dinic(3,4)==k) { printf("%d",day); break;}
		}
			
	}
}
void _1907()
{
	int x,co=0;
	s=n*m+1;t=n*m+2;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	{
		co=(i+j)%2;
		int u=(i-1)*m+j;scanf("%d",&x); tot+=x;
		if(!co)
		{
			add_edge(s,u,x);
			check_and_add(i,j,-1,0);
			check_and_add(i,j,1,0);
			check_and_add(i,j,0,-1);
			check_and_add(i,j,0,1);	
		} 
		else add_edge(u,t,x);
	}
	printf("%d",tot-Dinic(s,t));
}
int main()                                 
{
	if(special_read()) _1908();
	else _1907(); 
	
	return 0;	
}标签:目的 set order 检查 方法 ios ext 思路 idt
原文地址:http://www.cnblogs.com/zj75211/p/6659240.html