您的位置:首页 > 其它

[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。。。

#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();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: