POJ1637 Sightseeing tour(混合尤拉圖的判斷)
阿新 • • 發佈:2019-01-03
給出一張混合圖(有有向邊,也有無向邊),判斷是否存在歐拉回路。
首先是對圖中的無向邊隨意定一個方向,然後統計每個點的入度(indeg)和出度(outdeg),如果(indeg - outdeg)是奇數的話,一定不存在歐拉回路;
如果所有點的入度和出度之差都是偶數,那麼就開始網路流構圖:
1,對於有向邊,捨棄;對於無向邊,就按照最開始指定的方向建權值為 1 的邊;
2,對於入度小於出度的點,從源點連一條到它的邊,權值為(outdeg - indeg)/2;出度小於入度的點,連一條它到匯點的權值為(indeg - outdeg)/2 的邊;
構圖完成,如果滿流(求出的最大流值 == 和匯點所有連邊的權值之和),那麼存在歐拉回路,否則不存在。
#include<cstdio> #include<cstring> #include<queue> #include<climits> #define find_min(a,b) a<b?a:b using namespace std; const int N = 210; struct Edge{ int s,e,v,next; }edge[10*N]; int n,m,e_num,cnt,head[N],d[N],sp,tp; int sum,indeg[N],outdeg[N]; void AddEdge(int a,int b,int c){ edge[e_num].s=a; edge[e_num].e=b; edge[e_num].v=c; edge[e_num].next=head[a]; head[a]=e_num++; edge[e_num].s=b; edge[e_num].e=a; edge[e_num].v=0; edge[e_num].next=head[b]; head[b]=e_num++; } void init(){ int i,a,b,c; scanf("%d%d",&n,&m); e_num=0; memset(head,-1,sizeof(head)); memset(indeg,0,sizeof(indeg)); memset(outdeg,0,sizeof(outdeg)); for(i=0;i<m;i++){ scanf("%d%d%d",&a,&b,&c); indeg[b]++; outdeg[a]++; if(c==0) AddEdge(a,b,1); } } void getmap(){ int i; sum=0; for(i=1;i<=n;i++){//有向邊建圖,無向邊捨棄 if(indeg[i] < outdeg[i]) AddEdge(0,i,(outdeg[i]-indeg[i])/2); else if(indeg[i] > outdeg[i]){ AddEdge(i,n+1,(indeg[i]-outdeg[i])/2); sum+=(indeg[i]-outdeg[i])/2; } } } int bfs(){ queue <int> q; memset(d,-1,sizeof(d)); d[sp]=0; q.push(sp); while(!q.empty()){ int cur=q.front(); q.pop(); for(int i=head[cur];i!=-1;i=edge[i].next){ int u=edge[i].e; if(d[u]==-1 && edge[i].v>0){//沒有標記,且可行流大於0 d[u]=d[cur]+1; q.push(u); } } } return d[tp] != -1;//匯點是否成功標號,也就是說是否找到增廣路 } int dfs(int a,int b){//a為起點 int r=0; if(a==tp)return b; for(int i=head[a];i!=-1 && r<b;i=edge[i].next){ int u=edge[i].e; if(edge[i].v>0 && d[u]==d[a]+1){ int x=find_min(edge[i].v,b-r); x=dfs(u,x); r+=x; edge[i].v-=x; edge[i^1].v+=x; } } if(!r)d[a]=-2; return r; } int dinic(int sp,int tp){ int total=0,t; while(bfs()){ while(t=dfs(sp,INT_MAX)) total+=t; } return total; } void solve(){ int i,flag=1; for(i=1;i<=n;i++){ if( (indeg[i]-outdeg[i])%2==1 ){ flag=0;break; } } if(!flag)puts("impossible"); else{ getmap(); int ans=dinic(sp,tp); if(sum==ans) puts("possible"); else puts("impossible"); } } int main() { int t; scanf("%d",&t); while(t--) { init(); sp=0; tp=n+1; solve(); } return 0; }