[POJ1637]SightseeingTour
2016-02-19 20:52
239 查看
题目大意:给出一个含有有向边和无向边的图,求是否存在一条欧拉回路。
很明显地,一个有向图有欧拉回路当且仅当入度等于出度。我们可以把无向边强制设定一个方向,然后再调整。
那么我们如何调整。
我们先计算每个点的入度和出度,若和为奇数,则必无解。
若in[u]>out[u]in[u]>out[u]则把这个点和汇点连一条边,容量为(in[u]−out[u])÷2(in[u]-out[u])
\div 2
否则从源点连过来,容量是上面的相反数。。。
然后再把确定方向的无向边容量设为1,跑最大流,如果满流才有解。
这是为什么,因为对于每一条边,你改变它的方向,就会使得边上两点的出入度差减2,所以我们需要更改(in[u]−out[u])÷2(in[u]-out[u])
\div 2或(out[u]−in[u])÷2(out[u]-in[u])\div 2条边,哪些边呢?
德霸哥说:“交给网络流”!
于是此题便迎刃而解。
我ifndef好像WA了,搞了我20min。QAQ。。。
很明显地,一个有向图有欧拉回路当且仅当入度等于出度。我们可以把无向边强制设定一个方向,然后再调整。
那么我们如何调整。
我们先计算每个点的入度和出度,若和为奇数,则必无解。
若in[u]>out[u]in[u]>out[u]则把这个点和汇点连一条边,容量为(in[u]−out[u])÷2(in[u]-out[u])
\div 2
否则从源点连过来,容量是上面的相反数。。。
然后再把确定方向的无向边容量设为1,跑最大流,如果满流才有解。
这是为什么,因为对于每一条边,你改变它的方向,就会使得边上两点的出入度差减2,所以我们需要更改(in[u]−out[u])÷2(in[u]-out[u])
\div 2或(out[u]−in[u])÷2(out[u]-in[u])\div 2条边,哪些边呢?
德霸哥说:“交给网络流”!
于是此题便迎刃而解。
我ifndef好像WA了,搞了我20min。QAQ。。。
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<iostream> #include<queue> #include<vector> #define X first #define Y second #define MP make_pair #define LL long long #define pb push_back #define INF 0x3f3f3f3f #define DEBUG(...) fprintf(stderr,__VA_ARGS__) using namespace std; const int MAXN=300,MAXM=5000; int n,m,in[MAXN],out[MAXN]; struct Edge{ int u,v,flow,cap; Edge(int u=0,int v=0,int flow=0,int cap=0):u(u),v(v),flow(flow),cap(cap){} }; vector<Edge> tmp; struct Dinic{ vector<int> G[MAXN]; int cur[MAXN],dis[MAXN],S,T,vis[MAXN]; vector<Edge> edges; void clear() { for(int i=0;i<MAXN;i++)G[i].clear(); edges.clear(); memset(cur,0,sizeof(cur)); memset(dis,INF,sizeof(dis)); } void add(int a,int b,int c) { edges.pb(Edge(a,b,0,c)); edges.pb(Edge(b,a,0,0)); int k=edges.size(); G[a].pb(k-2); G[b].pb(k-1); } bool BFS() { memset(vis,0,sizeof(vis)); dis[S]=0; queue<int> q; q.push(S); vis[S]=1; while(!q.empty()) { int u=q.front();q.pop(); for(int i=0;i<G[u].size();i++) { Edge& e=edges[G[u][i]]; if(!vis[e.v]&&e.cap>e.flow) { vis[e.v]=1; dis[e.v]=dis[u]+1; q.push(e.v); } } } return vis[T]; } int DFS(int u,int a) { if(u==T||a==0)return a; int f=INF,flow=0; for(int& i=cur[u];i<G[u].size();i++) { Edge& e=edges[G[u][i]]; if(dis[u]+1==dis[e.v]&&(f=DFS(e.v,min(a,e.cap-e.flow))>0)) { e.flow+=f; edges[G[u][i]^1].flow-=f; flow+=f; a-=f; if(a==0)break; } } return flow; } void maxflow() { dis[S]=0; while(BFS()) { memset(cur,0,sizeof(cur)); DFS(S,INF); } } bool judge() { for(int i=0;i<edges.size();i++) { Edge& e=edges[i]; if(e.v==T&&e.flow!=e.cap) return 0; } return 1; } }Graph; void init() { Graph.clear(); tmp.clear(); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); scanf("%d %d",&n,&m); Graph.S=n+1,Graph.T=n+2; for(int i=1;i<=m;i++) { int a,b,c; scanf("%d %d %d",&a,&b,&c); if(c==1) { out[a]++; in[b]++; } else { tmp.pb(Edge(a,b,0,1)); out[a]++; in[b]++; } } } void solve() { int s=n+1,t=n+2; for(int i=1;i<=n;i++) { if((in[i]+out[i])&1) { puts("impossible"); return; } else { if(in[i]==out[i]) continue; if(in[i]>out[i]) Graph.add(i,t,(in[i]-out[i])/2); else Graph.add(s,i,(-in[i]+out[i])/2); } } for(int i=0;i<tmp.size();i++) Graph.add(tmp[i].u,tmp[i].v,tmp[i].cap); Graph.maxflow(); if(Graph.judge()) puts("possible"); else puts("impossible"); return; } int main() { #ifndef ONLINE_JUDGE freopen("tour.in","r",stdin); freopen("tour.out","w",stdout); #endif int t; scanf("%d",&t); while(t--) { init(); solve(); } }
相关文章推荐
- android复习计划
- unity 优化
- Impression of the ITOO ‘s conference
- 代码结构和标识符
- XML文件读取
- python sched实现任务调度
- Eclipse的使用及Java程序的标识符和关键字
- codeforces 630A Again Twenty Five!
- 单点登录cas常见问题(五) - service有哪些存储方式?
- 希望ntsd可以干掉dgagent
- 超载监控项目
- java实现二分检索树
- c/c++题目汇总一
- rocketmq3.26研究之五DefaultMQPushConsumer
- 81. Search in Rotated Sorted Array II
- codeforces 630C Lucky Numbers
- 如何从被领导到领导别人
- 安卓 bitmap绘图
- php错误及异常
- 10022---varnish配置详解