标签:
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 964 Accepted Submission(s): 390
一道水题,只需注意先判断图的连通性即可,然后就是直接套模板就可以ac
谁要是有闲工夫可以研究一下这两个测试数据
1:
4
a 0
b 0
bc 0
ac 1
2:
4
a 0
b 0
bc 0
ca 1
#include<iostream> #include<queue> #include<cstring> #include<cstdio> #include<climits> #define MAXE 1800 #define MAXP 30 #define Max(a,b) a>b?a:b #define Min(a,b) a<b?a:b using namespace std; struct Edge { int s,t,f,next; } edge[MAXE]; int head[MAXP]; int cur[MAXP]; int pre[MAXP]; int stack[MAXE]; int used[MAXP]; int fa[MAXP]; int degree[MAXP]; int ent; int sum; int n,m,s,t,supers,supert; int num; int find(int x) { while(fa[x]!=x) x=fa[x]; return x; } void add(int start,int last,int f) { edge[ent].s=start; edge[ent].t=last; edge[ent].f=f; edge[ent].next=head[start]; head[start]=ent++; edge[ent].s=last; edge[ent].t=start; edge[ent].f=0; edge[ent].next=head[last]; head[last]=ent++; } bool bfs(int S,int T) { memset(pre,-1,sizeof(pre)); pre[S]=0; queue<int>q; q.push(S); while(!q.empty()) { int temp=q.front(); q.pop(); for(int i=head[temp]; i!=-1; i=edge[i].next) { int temp2=edge[i].t; if(pre[temp2]==-1&&edge[i].f) { pre[temp2]=pre[temp]+1; q.push(temp2); } } } return pre[T]!=-1; } int dinic(int start,int last) { int flow=0,now; while(bfs(start,last)) { int top=0; memcpy(cur,head,sizeof(head)); int u=start; while(1) { if(u==last)//如果找到终点结束对中间路径进行处理并计算出该流 { int minn=INT_MAX; for(int i=0; i<top; i++) { if(minn>edge[stack[i]].f) { minn=edge[stack[i]].f; now=i; } } flow+=minn; for(int i=0; i<top; i++) { edge[stack[i]].f-=minn; edge[stack[i]^1].f+=minn; } top=now; u=edge[stack[top]].s; } for(int i=cur[u]; i!=-1; cur[u]=i=edge[i].next) //找出从u点出发能到的边 if(edge[i].f&&pre[edge[i].t]==pre[u]+1) break; if(cur[u]==-1)//如果从该点未找到可行边,将该点标记并回溯 { if(top==0)break; pre[u]=-1; u=edge[stack[--top]].s; } else//如果找到了继续运行 { stack[top++]=cur[u]; u=edge[cur[u]].t; } } } return flow; } int main() { int cas; scanf("%d",&cas); for(int times=1;times<=cas;times++) { memset(head,-1,sizeof(head)); memset(used,0,sizeof(used)); memset(degree,0,sizeof(degree));//初始化的过程 ent=0; s=0,t=27; scanf("%d",&n); char str[25]; int mark; for(int i=1;i<=26;i++) fa[i]=i; for(int i=1;i<=n;i++) { scanf("%s%d",str,&mark); int len=strlen(str); int u=str[0]-‘a‘+1; int v=str[len-1]-‘a‘+1; used[u]=1; used[v]=1; if(find(u)!=find(v)) { fa[find(v)]=find(u);//检查图的联通性的过程 } degree[u]--; degree[v]++; if(mark) add(u,v,1); } int ok=1; int temp=0; for(int i=1;i<=26;i++) { if(used[i]&&fa[i]==i) { temp++; } } if(temp!=1)ok=0;//判断图是否联通 temp=0; int v1=-1,v2=-1; for(int i=1;i<=26;i++) { if(degree[i]%2==1)//找出度数为奇数的点并记录下来 { temp++; v1=i; } if(degree[i]%2==-1) { temp++; v2=i; } } if(temp==0||(temp==2&&v1!=-1&&v2!=-1)) { if(temp==2) { add(v1,v2,1);//如果有两个点的度数为奇数且这两个点一个入度大于出度,一个出度大于入度,则将这两个点连上 degree[v1]--; degree[v2]++; } } else ok=0; printf("Case %d: ",times); temp=0; if(!ok)printf("Poor boy!\n"); else { for(int i=1;i<=26;i++) { if(degree[i]>0) add(i,t,degree[i]/2); else if(degree[i]<0) { add(s,i,-degree[i]/2); temp+=-degree[i]/2; } } if(dinic(s,t)==temp)printf("Well done!\n");//如果跑出来的最大流正好能使得与s点相连的边都满流,则表示符合要求 else printf("Poor boy!\n"); } } return 0; }
标签:
原文地址:http://www.cnblogs.com/lthb/p/4458218.html