Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 8628 | Accepted: 3636 |
Description
Input
Output
Sample Input
4 5 8 2 1 0 1 3 0 4 1 1 1 5 0 5 4 1 3 4 0 4 2 1 2 2 0 4 4 1 2 1 2 3 0 3 4 0 1 4 1 3 3 1 2 0 2 3 0 3 2 0 3 4 1 2 0 2 3 1 1 2 0 3 2 0
Sample Output
possible impossible impossible possible
题意:给你一个图,其中既有有向边又有无向边,要你判断图中是否存在欧拉回路。
这题难点就在于讨论无向边的方向。首先,欧拉回路图有个性质:所有点的入度等于出度。然后又发现,对于某点连出去的一条无向边,改变它的方向,这个点的(出度-入度)奇偶性不变。所以先给无向边随意定向,然后判断是否有点的(出度-入度)为奇数,有就绝逼不可能有欧拉回路。
然而到这里还没有完,每个点的(出度-入度)都为偶数并不代表改变那些无向边的方向就可以形成一个欧拉回路图。
现在的问题类似于网络流的分配问题,设一个点的(出度-入度)为d,那么将d大于零的点和d小于零的点分成两个集合,保留原来的无向边,容量为1……具体还是看程序吧。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 6 using namespace std; 7 const int INF=2147483647; 8 const int maxn=210,maxm=20010; 9 int cnt,fir[maxn],nxt[maxm],cap[maxm],to[maxm],dis[maxn],gap[maxn],path[maxn]; 10 int In[maxn],Out[maxn]; 11 void addedge(int a,int b,int c) 12 { 13 nxt[++cnt]=fir[a]; 14 to[cnt]=b; 15 cap[cnt]=c; 16 fir[a]=cnt; 17 } 18 19 bool BFS(int S,int T) 20 { 21 memset(dis,0,sizeof(dis)); 22 dis[T]=1; 23 queue<int>q;q.push(T); 24 while(!q.empty()) 25 { 26 int node=q.front();q.pop(); 27 for(int i=fir[node];i;i=nxt[i]) 28 { 29 if(dis[to[i]])continue; 30 dis[to[i]]=dis[node]+1; 31 q.push(to[i]); 32 } 33 } 34 return dis[S]; 35 } 36 int fron[maxn]; 37 int ISAP(int S,int T) 38 { 39 if(!BFS(S,T)) 40 return 0; 41 for(int i=1;i<=T;i++)++gap[dis[i]]; 42 int p=S,ret=0; 43 memcpy(fron,fir,sizeof(fir)); 44 while(dis[S]<=T+1) 45 { 46 if(p==T){ 47 int f=INF; 48 while(p!=S){ 49 f=min(f,cap[path[p]]); 50 p=to[path[p]^1]; 51 } 52 p=T;ret+=f; 53 while(p!=S){ 54 cap[path[p]]-=f; 55 cap[path[p]^1]+=f; 56 p=to[path[p]^1]; 57 } 58 } 59 int &ii=fron[p]; 60 for(;ii;ii=nxt[ii]){ 61 if(!cap[ii]||dis[to[ii]]+1!=dis[p]) 62 continue; 63 else 64 break; 65 } 66 67 if(ii){ 68 p=to[ii]; 69 path[p]=ii; 70 } 71 72 73 else{ 74 if(--gap[dis[p]]==0)break; 75 int minn=T+1; 76 for(int i=fir[p];i;i=nxt[i]) 77 if(cap[i]) 78 minn=min(minn,dis[to[i]]); 79 gap[dis[p]=minn+1]++; 80 fron[p]=fir[p]; 81 if(p!=S) 82 p=to[path[p]^1]; 83 } 84 } 85 return ret; 86 } 87 88 void Init() 89 { 90 memset(fir,0,sizeof(fir)); 91 memset(gap,0,sizeof(gap)); 92 memset(In,0,sizeof(In)); 93 memset(Out,0,sizeof(Out)); 94 cnt=1; 95 } 96 int main() 97 { 98 int T,n,m; 99 scanf("%d",&T); 100 while(T--) 101 { 102 Init(); 103 scanf("%d%d",&n,&m); 104 for(int i=1;i<=m;i++) 105 { 106 int u,v,k; 107 scanf("%d%d%d",&u,&v,&k); 108 In[v]++;Out[u]++; 109 if(!k) 110 addedge(u,v,1),addedge(v,u,0); 111 } 112 int flag=1; 113 for(int i=1;i<=n;i++){ 114 int d=Out[i]-In[i]; 115 if(d&1){ 116 flag=0; 117 break; 118 } 119 if(d>0)addedge(0,i,d/2),addedge(i,0,0); 120 if(d<0)addedge(i,n+1,d/(-2)),addedge(n+1,i,0); 121 } 122 if(flag) 123 ISAP(0,n+1); 124 for(int i=fir[0];i;i=nxt[i]) 125 if(cap[i]) 126 flag=0; 127 128 if(flag) 129 puts("possible"); 130 else 131 puts("impossible"); 132 } 133 return 0; 134 }
最后感谢邝斌的题解,%%%
网络流(最大流) POJ 1637 Sightseeing tour
原文:http://www.cnblogs.com/TenderRun/p/5225044.html