HDU 3472 HS BDC 混合图的欧拉路径判断 (网络流)
2017-10-11 21:54
387 查看
HDU 3472 HS BDC 混合图的欧拉路径判断
题意:给n个字符串,这些字符串如果某个字符串的尾部字母和另一个字符串的首部字母相等,那么这两个字母就可以连起来,有的字符串可以反转,问是否存在一种情况使得所有字符串都连成一条链。思路:
字符串的首字母–>字符串的尾字母建一条有向边,如果字符串是可反转的,那么就建无向边,
那么问题就转换为:
是否存在一种无向边定向方案,使得这个图中存在这么一条欧拉路径。
给欧拉路径的终点->起点(度数为奇的点)加条边,边权为1,使之成为欧拉回路。
首先任意定向无向边为有向边。建图的时候,若为无向边则加边,方向任意定,边权为1。否则不加边,因为有向边已经不能改变,然后记录每个节点的出度和入度的差。
设差为k,k如果为偶数的话,那么如果我改变k/2条与这个节点相关的边就可以使得这个节点的 出度=入度。
k如果为奇数的话,假设有两个节点的k为奇数那么其中一个是起点另一个是终点。从终点到起点建一条边,边权为1
如果差为k>0,那么说明 出度>入度,需要减少出度增加入度来使得 出度=入度,超级源点->该点,边权为k/2
如果差为k<0,那么说明 出度<入度,需要增加出度减少入度来使得 出度=入度,该点->超级汇点,边权为-k/2
如果差为k=0,那么说明 出度=入度。
如此建图之后判满流,如果满流则说明存在欧拉回路,是欧拉图。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <queue> #include <set> #include <algorithm> #include <limits.h> #define LL long long #define N 1010 #define M 10010 #define inf 10000000 using namespace std; const int INF = INT_MAX; struct Edge{ int from, to, w, nxt; }ed[M << 2]; int head , idc = 1, S, T; int dis ; int top, sta , last ; void init(){ memset(head, 0, sizeof(head)); idc = 1; } void adde(int u, int v, int w){ ed[++idc].from = u; ed[idc].to = v; ed[idc].w = w; ed[idc].nxt = head[u]; head[u] = idc; } bool bfs(){ memset(dis, -1, sizeof(dis)); queue <int> q; q.push(S); dis[S]=0; while( !q.empty() ){ int u = q.front(); q.pop(); for(int k=head[u]; k; k=ed[k].nxt) { int v = ed[k].to; if(ed[k].w && dis[v] == -1){ dis[v] = dis[u] + 1; q.push( v ); if(v == T) break; } } } memcpy(last, head, sizeof(head)); return dis[T] != -1; } int find(int u, int low){ if (u==T || low==0) return low; int totflow =0; for(int k=last[u]; k; last[u]=k=ed[k].nxt){ int v = ed[k].to; if(ed[k].w && dis[v] == dis[u] + 1){ int f = find(v, min(low,ed[k].w)); ed[k].w -= f; ed[k^1].w += f; totflow += f; low -= f; if(low == 0) return totflow; } } if( !totflow ) dis[u] = -1; return totflow; } LL Dinic(){ LL ans = 0; while (bfs()) ans += find(S, INF); return ans; } int du[30]; int fa[30], use[30]; int findfa(int x){ return x==fa[x] ? x : fa[x] = findfa(fa[x]); } int Union(int x, int y){ x = findfa(x), y = findfa(y); if(x == y) return false; fa[x] = y; return true; } int main(){ int t, n, cas=0; char ch[30]; scanf("%d", &t); while( t-- ){ scanf("%d", &n); init(); for(int i=0; i<26; i++){ fa[i] = i; use[i] = 0; du[i] = 0; } for(int i=0; i<n; i++){ int x; scanf("%s%d", ch, &x); int st = ch[0] - 'a'; int ed = ch[strlen(ch) - 1] - 'a'; du[st]++; du[ed]--; use[st] = 1; use[ed] = 1; if( x ) adde(st, ed, 1), adde(ed, st, 0); Union(st, ed); } int num1 = 0, num2 = 0; S = -1, T = -1; for(int i=0; i<26; i++) if( use[i] ){ if(fa[i] == i) ++num1;//连通块个数 if(du[i] % 2){ ++num2;//奇度数的点的个数(作为欧拉路径的起始点,终止点) if(du[i] < 0) S = i; if(du[i] > 0) T = i; } } printf("Case %d: ", ++cas); if(num1!=1 || num2==1 || num2>2 || (num2==2 && (S==-1 || T==-1))){ puts("Poor boy!"); continue; } if(num2 == 2) adde(T, S, 1), adde(S, T, 0); S = 26, T = 27; LL sum = 0; for(int i=0; i<26; i++) //流量为1,度数改变2 if(du[i] > 0) adde(S, i, du[i] >> 1), adde(i, S, 0), sum += du[i] >> 1; else if(du[i] < 0) adde(i, T, -du[i] >> 1), adde(T, i, 0); if(Dinic() != sum) puts("Poor boy!"); else puts("Well done!"); } return 0; }
相关文章推荐
- HDU 3472 HS BDC (混合图的欧拉路径判断)
- HDU 3472 HS BDC 混合图欧拉路径 最大流
- HDU 3472 HS BDC 混合图的欧拉路径
- hdu 3472 HS BDC 混合欧拉 网络流
- hdu 3472 HS BDC 混合欧拉 网络流
- HDU 3472 HS BDC 混合图欧拉回路 网络流
- hdu 3472 HS BDC(混合欧拉路径)
- hdu 3472 HS BDC(混合路的欧拉路径)
- hdu 3472 混合图的欧拉路径
- HDOJ 3472 - HS BDC 判断混合图是否存在欧拉通路
- HDU 3472 混合图欧拉回路 + 网络流
- hdu3472(混合图欧拉路径判断)
- HDU 3472 混合图欧拉回路 + 网络流
- HS BDC (hdu 3472 混合图的欧拉回路)
- HDU 3018 Ant Trip(欧拉路径 + 并查集 + 连通性判断)
- POJ - 1637 Sightseeing tour (混合图欧拉路径欧拉图判断)
- 【混合欧拉】 HDOJ 3472 HS BDC
- HDU 3472 HS BDC 混合欧拉回路通路
- HDU 5883 The Best Path 欧拉路径/回路
- nyoj 单词拼接(并查集判断连通性+欧拉路径)