HDU 3472 HS BDC 混合图欧拉路径 最大流
2017-09-07 23:42
555 查看
暑假的时候做过混合图的欧拉回路,然后这次碰到的是欧拉路径。
欧拉回路网上都有详细的题解,不多说了。
然后这题主要是“路径”,所以有些区别。路径的话就可能存在一个起点一个终点,它们的度数一定是奇数。
所以做这题分以下几步。
1. 判断连通性。
2. 把原来的无向边默认一个方向去修改两个点的入度和出度,然后在图中加一条反向边,容量为1。
3. 找到度数为奇数的点,只可能为2个或0个。如果为2个,在这两点随意连边,修改度数,再加反向边,容量为1。
4. 通过每个点的入度和出度差判断是和源点连边还是和汇点连边。
5. 跑最大流,判断是否满流。
这题的数据应该是挺水的,我跑了15ms就过了。
网上有些题解的代码好像是不对的。
欧拉回路网上都有详细的题解,不多说了。
然后这题主要是“路径”,所以有些区别。路径的话就可能存在一个起点一个终点,它们的度数一定是奇数。
所以做这题分以下几步。
1. 判断连通性。
2. 把原来的无向边默认一个方向去修改两个点的入度和出度,然后在图中加一条反向边,容量为1。
3. 找到度数为奇数的点,只可能为2个或0个。如果为2个,在这两点随意连边,修改度数,再加反向边,容量为1。
4. 通过每个点的入度和出度差判断是和源点连边还是和汇点连边。
5. 跑最大流,判断是否满流。
这题的数据应该是挺水的,我跑了15ms就过了。
网上有些题解的代码好像是不对的。
#include <iostream> #include <cstring> #include <string> #include <cstdio> #include <algorithm> #include <queue> using namespace std; const int MAXN = 100; const int MAXM = 5000; const int inf = 0x3f3f3f3f; char s[1500]; int n,mp[MAXN][MAXN],head[MAXN]; int dis[MAXN],in[MAXN],out[MAXN],tol,pre[MAXN]; bool vis[MAXN]; struct Edge { int to,cap,flow,nex; Edge(int to,int cap,int flow,int nex):to(to),cap(cap),flow(flow),nex(nex) {} Edge() {} }edge[MAXM]; void init() { memset(in,0,sizeof in); memset(out,0,sizeof out); memset(head,-1,sizeof head); memset(vis,0,sizeof vis); tol=0; for (int i=0;i<MAXN;i++) pre[i]=i; } int find(int p) { return pre[p]==p?p:pre[p]=find(pre[p]); } void join(int a,int b) { int u=find(a),v=find(b); if (u!=v) pre[u]=v; } void addedge(int u,int v,int cap) { edge[tol]=Edge(v,cap,0,head[u]); head[u]=tol++; edge[tol]=Edge(u,0,0,head[v]); head[v]=tol++; } int getnum(char ch) { return ch-'a'+1; } bool bfs(int s,int t) { memset(dis,-1,sizeof dis); dis[s]=0; queue<int> que; que.push(s); while (!que.empty()) { int u=que.front();que.pop(); for (int i=head[u];~i;i=edge[i].nex) { int v=edge[i].to; if (dis[v]==-1 && edge[i].cap>edge[i].flow) { dis[v]=dis[u]+1; if (v==t) return true; que.push(v); } } } return false; } int dfs(int u,int t,int cap) { if (u==t) return cap; int flow=0,f; for (int i=head[u];~i;i=edge[i].nex) { int v=edge[i].to; if (dis[v] == dis[u]+1 && edge[i].cap>edge[i].flow) { f=dfs(v,t,min(cap-flow,edge[i].cap-edge[i].flow)); edge[i].flow += f; edge[i^1].flow -= f; flow += f; if (flow == cap) break; } } if (!flow) dis[u]=-1; return flow; } int dicnic(int s,int t) { int flow=0,a; while (bfs(s,t)) while ((a=dfs(s,t,inf))>0) flow+=a; return flow; } int main() { int t,tt=0,tag; cin>>t; while (t--) { init(); cin>>n; for (int i=1;i<=n;i++) { scanf("%s%d",s,&tag); int a=getnum(s[0]); int b=getnum(s[strlen(s)-1]); vis[a]=vis[b]=true; out[a]++; in[b]++; join(a,b); if (tag == 1) addedge(b,a,1); } int cnt=0,sum=0,v1=0,v2=0; bool flag=false; for (int i=1;i<=26;i++) if (vis[i]) for (int j=1;j<=26;j++) if (vis[j] && find(i)!=find(j)) flag=true; for (int i=1;i<=26;i++) { int k=in[i]-out[i]; if (k&1) { cnt++; if (v1) v2=i; else v1=i; } } printf("Case %d: ",++tt); if (cnt != 2 && cnt!=0) flag=true; if (cnt == 2) { out[v1]++; in[v2]++; addedge(v2,v1,1); } if (flag) { printf("Poor boy!\n"); continue; } for (int i=1;i<=26;i++) { int k=in[i]-out[i]; if (!k) continue; if (k>0) addedge(0,i,k/2) , sum+=k/2; if (k<0) addedge(i,27,-k/2); } int ans=dicnic(0,27); if (ans == sum ) printf("Well done!\n"); else printf("Poor boy!\n"); } 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 混合图的欧拉路径
- hdu 3472 HS BDC 混合欧拉 网络流
- HDU 3472 HS BDC(混合欧拉图(使用最大流))模板
- 混合边的欧拉路径——poj1637 最大流
- poj 1637 Sightseeing tour(混合图欧拉路径判定 最大流)
- HDU 3472 HS BDC 混合图欧拉回路 网络流
- HDU 3472 HS BDC 混合欧拉回路通路
- HS BDC (hdu 3472 混合图的欧拉回路)
- 【混合欧拉】 HDOJ 3472 HS BDC
- HDOJ 3472 - HS BDC 判断混合图是否存在欧拉通路
- HDU 4862 Jump(最大k路径覆盖 费用流)
- hdu 4850 Wow! Such String! 构造 或 欧拉路径并改写成非递归版本
- HDU 1116(并查集,欧拉路径)
- HDU 1151Air Raid 最小路径覆盖=n-最大匹配量 (第二道二分匹配)