您的位置:首页 > 其它

hdu3472(混合图欧拉路径判断)

2016-06-14 20:38 363 查看
链接:点击打开链接

题意:有n个单词,有的可以前后颠倒,看是否可以将n个单词首尾相连

代码:#include <set>
#include <queue>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
const int INF=0x3f3f3f3f;
struct node{
int u,v,cap;
node(){}
node(int u,int v,int cap):u(u),v(v),cap(cap){}
}es[1005*1005];
int R,S,T;
int dis[1005],deg[1005],iter[1005];
vector<int> tab[1005];
void addedge(int u, int v, int cap){
tab[u].push_back(R);
es[R++]=node(u,v,cap);
tab[v].push_back(R);
es[R++]=node(v,u,0);
}
int bfs(){
int i,h;
queue<int> q;
q.push(S);
memset(dis,INF,sizeof(dis));
dis[S]=0;
while(q.size()){
h=q.front();
q.pop();
for(i=0;i<tab[h].size();i++){
node &e=es[tab[h][i]];
if(e.cap>0&&dis[e.v]==INF){
dis[e.v]=dis[h]+1;
q.push(e.v);
}
}
}
return dis[T]<INF;
}
int dfs(int x,int maxflow){
int flow;
if(x==T)
return maxflow;
for(int &i=iter[x];i<tab[x].size();i++){
node &e=es[tab[x][i]];
if(dis[e.v]==dis[x]+1&&e.cap>0){
flow=dfs(e.v,min(maxflow,e.cap));
if(flow){
e.cap-=flow;
es[tab[x][i]^1].cap+=flow;
return flow;
}
}
}
return 0;
}
int dinic(){
int ans,flow;
ans=0;
while(bfs()){
memset(iter,0,sizeof(iter));
while(flow=dfs(S,INF))
ans+=flow;
}
return ans;
}
int par[1005],sign[50];
void init(int n){
int i;
for(i=0;i<=n;i++)
par[i]=i;
}
int found(int x){
if(par[x]==x)
return par[x];
return par[x]=found(par[x]);
}
void unite(int x,int y){
x=found(x);
y=found(y);
if(x==y)
return;
par[x]=y;
}
bool same(int x,int y){
return found(x)==found(y);
}
bool judge(){
int i,j;
for(i=1;i<=26;i++)
for(j=i+1;j<=26;j++)
if(sign[i]&&sign[j]&&(same(i,j)==0))
return 0;
return 1;
}
int main(){ //http://yzmduncan.iteye.com/blog/1149049
int n,i,j,t,c1,c2,st,en,cas,num,sum; //这个讲的很详细
char s[55];
scanf("%d",&t);
for(cas=1;cas<=t;cas++){
scanf("%d",&n);
R=S=0,T=27;
init(26);
for(i=0;i<=T;i++)
tab[i].clear();
memset(deg,0,sizeof(deg));
memset(sign,0,sizeof(sign));
for(i=0;i<n;i++){
scanf("%s%d",s,&num);
c1=s[0]-'a'+1;
c2=s[strlen(s)-1]-'a'+1;
deg[c1]--,deg[c2]++;
sign[c1]=sign[c2]=1;
if(num)
addedge(c1,c2,1);
unite(c1,c2);
}
if(judge()==0){ //并查集判断图是否联通
printf("Case %d: Poor boy!\n",cas);
continue;
}
sum=0;
st=en=-1;
for(i=1;i<=26;i++){ //如果是存在欧拉路径而不是欧拉回路
if(deg[i]%2==1||deg[i]%2==-1){ //找出起点和终点并变成欧拉回路
if(deg[i]%2==1)
en=i;
else
st=i;
sum++;
}
}
if(sum==0||(sum==2&&st!=-1&&en!=-1))
addedge(en,st,1);
else{
printf("Case %d: Poor boy!\n",cas);
continue;
}
sum=0;
for(i=1;i<=26;i++){ //因为每跑一条无向边两边的值相当于减2
if(deg[i]<0){ //因此与源点汇点相连的点的值除二
sum+=(-deg[i]/2);
addedge(S,i,-deg[i]/2);
}
else if(deg[i]>0)
addedge(i,T,deg[i]/2);
}
if(sum==dinic())
printf("Case %d: Well done!\n",cas);
else
printf("Case %d: Poor boy!\n",cas);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: