找的是欧拉回路而不是欧拉道路。
一直在尝试用无向图和有向图的欧拉回路算法来解决混合图的问题,最后发现不可能实现,因为无向图的度数和有向图的入出度在理论上无法统一,无论怎么拆边建图都不行。
一条无向边可以当成两种有向边之一使用,把无向边换成某种有向边,想办法找到符合条件的有向图即可,但枚举又肯定超时。
符合欧拉回路的有向图要求每个点入度和出度相等。不知该如何动态地调整这些无向边。
网络流模型真是个神奇的东西。
代码
#include<stdio.h>
#include<vector>
#include<queue>
#include<string.h>
#include<stack>
#define maxn 110
#define INF 0X3F3F3F3F
using namespace std;
struct Edge
{
int from,to,cap,flow;
Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
};
struct EdmondsKarp
{
int n,m;
vector<Edge>edges;
vector<int>G[maxn];
int a[maxn];
int p[maxn];
void init(int n)
{
this->n=n;
for(int i=0;i<=n;i++) G[i].clear();
edges.clear();
}
void AddEdge(int from,int to,int cap)
{
edges.push_back(Edge(from,to,cap,0));
edges.push_back(Edge(to,from,0,0));
m=edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}
int Maxflow(int s,int t)
{
int flow=0;
for(;;)
{
memset(a,0,sizeof(a));
queue<int>Q;
Q.push(s);
a[s]=INF;
while(!Q.empty())
{
int x=Q.front();Q.pop();
for(unsigned int i=0;i<G[x].size();i++)
{
Edge& e=edges[G[x][i]];
if(!a[e.to]&&e.cap>e.flow)
{
p[e.to]=G[x][i];
a[e.to]=min(a[x],e.cap-e.flow);
Q.push(e.to);
}
}
if(a[t]) break;
}
if(!a[t]) break;
for(int u=t;u!=s;u=edges[p[u]].from)
{
edges[p[u]].flow+=a[t];
edges[p[u]^1].flow-=a[t];
}
flow+=a[t];
}
return flow;
}
};
int G[maxn][maxn];
int id[maxn];
int od[maxn];
int V,E;
stack<int>s;
void euler(int u)
{
for(int v=1;v<=V;v++)
if(G[u][v])
{
G[u][v]--;
euler(v);
s.push(v);
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(G,0,sizeof(G));
memset(id,0,sizeof(id));
memset(od,0,sizeof(od));
scanf("%d %d",&V,&E);
EdmondsKarp EK;
EK.init(V+2);
int a,b;
char c;
for(int i=0;i<E;i++)
{
scanf("%d %d %c",&a,&b,&c);
id[b]++;
od[a]++;
if(c=='U') EK.AddEdge(a,b,1);
else G[a][b]++;
}
bool ok=true;
int ANS=0;
for(int i=1;i<=V;i++)
{
if((id[i]+od[i])%2) ok=false;
int NUM=od[i]-id[i];
if(NUM>0) {EK.AddEdge(0,i,NUM/2);ANS+=NUM/2;}
if(NUM<0) EK.AddEdge(i,V+1,(-NUM)/2);
}
if(ok)
{
int ans=EK.Maxflow(0,V+1);
if(ans==ANS)
{
for(unsigned int i=0;i<EK.edges.size();i+=2)
{
Edge& e=EK.edges[i];
if(e.from==0) continue;
if(e.to==V+1) continue;
if(e.flow) G[e.to][e.from]++;
else G[e.from][e.to]++;
}
while(!s.empty()) s.pop();
euler(1);
printf("1");
while(!s.empty())
{
printf(" %d",s.top());
s.pop();
}
puts("");
}
else printf("No euler circuit exist\n");
}
else printf("No euler circuit exist\n");
puts("");
}
}