混合图欧拉回路POJ1637Sightseeing tour
http://www.cnblogs.com/looker_acm/archive/2010/08/15/1799919.html
/* ** 混合图欧拉回路 ** 只记录各定点的出度与入度之差,有向边无用丢弃,将无向边定向,在网络中建立流量为1的边 ** 另新建s和t。对于入 > 出的点u,连接边(u, t)、容量为x,对于出 > 入的点v,连接边(s, v), ** 容量为x(注意对不同的点x不同)。之后,察看是否有满流的分配,如果是满流则存在,否则不存在 */ #include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <cmath> using namespace std; const int maxn = 300; const int maxm = maxn*10; struct node{ int v,next,flow; }edge[maxm]; int head[maxn],dis[maxn],deg[maxn]; int id,source,sink; void add_edge(int u,int v,int flow){ edge[id].v = v;edge[id].flow = flow;edge[id].next = head[u];head[u] = id++; edge[id].v = u;edge[id].flow = 0 ;edge[id].next = head[v];head[v] = id++; } bool spfa(){ memset(dis,-1,sizeof(dis)); dis[source] = 0; queue<int>que; que.push(source); while(!que.empty()){ int u = que.front(); que.pop(); for(int id = head[u]; id != -1; id = edge[id].next){ int v = edge[id].v; if( edge[id].flow > 0 && dis[v] == -1){ dis[v] = dis[u] + 1; que.push(v); } } } return dis[sink] != -1; } int dinic(int u,int flow){ if( u == sink)return flow; int tmp = flow; for(int id = head[u]; id != -1; id = edge[id].next){ int v = edge[id].v; if( edge[id].flow > 0 && dis[v] == dis[u] + 1){ int tt = dinic(v,min(edge[id].flow ,tmp)); tmp -= tt; edge[id].flow -= tt; edge[id^1].flow += tt; if( tmp == 0)return flow; } } return flow - tmp; } int get_max(){ int max_flow = 0; while( spfa()) max_flow += dinic(source,100000); return max_flow; } int main(){ int t,n,m; int u,v,d; scanf("%d",&t); while( t-- ){ scanf("%d%d",&n,&m); for(int i = 0; i <= n+1; i++) deg[i] = 0,head[i] = -1; id = source = 0;sink = n+1; while( m-- ){ scanf("%d%d%d",&u,&v,&d); if( u == v)continue; deg[u]++,deg[v]--; if( d == 0)add_edge(u,v,1); } bool flg = false; int ans = 0; for(int i = 1;i <= n; i++){ if( deg[i]%2 ){flg = true;break;} deg[i] /= 2; if( deg[i] > 0){ ans += deg[i]; add_edge(source,i,deg[i]); } else add_edge(i,sink,-deg[i]); } if( flg || ans != get_max())puts("impossible"); else puts("possible"); } return 0; }