1. uoj#117 欧拉回路
给无向图和有向图两种图,判断是否存在并输出其欧拉回路
板子题。。。
无向图欧拉回路存在条件:所有点度数为偶数且所有边连通
有向图欧拉回路存在条件:所有点出度等于入度且所有边连通
#include<stdio.h>
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<math.h>
#include<string.h>
using namespace std;
const int N=1e6;
int p[N],head[N],nex[N],e=1;
int in[N],out[N],vis[N];
vector<int>g;
void add(int a,int b){
p[++e]=b;
nex[e]=head[a];
head[a]=e;
}
void dfs(int u){
int v,now;
for(int &i=head[u];i;i=nex[i]){ //需加当前弧优化,否则可卡到 m^2
if(vis[i/2]==0){
vis[i/2]=1;
v=p[i];
now=i;
dfs(v);
g.push_back(now);
}
}
}
int main(){
int a,b,i,n,m,t;
scanf("%d",&t); //t为1表示无向图,否则为有向图
scanf("%d%d",&n,&m);
if(m==0){
printf("YES\n");
return 0;
}
for(i=1;i<=m;i++){
scanf("%d%d",&a,&b);
if(t==1){
add(a,b);
add(b,a);
out[a]++;
out[b]++;
}
else{
add(a,b);
out[a]++;
in[b]++;
e++;
}
}
int ans=1;
if(t==1){
for(i=1;i<=n;i++) if(out[i]%2) ans=0;
}
else{
for(i=1;i<=n;i++) if(out[i]!=in[i]) ans=0;
}
if(ans==0) printf("NO\n");
else{
for(i=1;i<=n;i++) if(in[i]) a=i;
dfs(a);
if(g.size()!=m) printf("NO\n"); //判断边是否连通
else{
printf("YES\n");
for(i=g.size()-1;i>=0;i--){
a=g[i]/2;
if(g[i]%2) a*=-1;
printf("%d ",a);
}
}
}
}
2. UVA10735 混合图欧拉回路
由于图中存在无向边和有向边,不能直接判断是否存在欧拉回路,所以需要对无向边重新定向转成有向图处理。
先对所有的无向边任意定向,若定向后存在一个点的入度与出度差为奇数,则显然不存在欧拉回路(因为将一条无向边反向后端点入度与出度差的奇偶性不变,要想差变为0则初始差要为偶数)
任意定向无向边后,考虑使用网络流进行反悔操作
建图:
(1) 令d[i]=(out[i]-in[i])/2, 若d[i]>0,超级源点S向i连容量为d[i]的边;否则i向超级汇点T连容量为-d[i]的边
(2)对于一条定向为u -> v的无向边,u向v连容量为1的边
跑最大流,不是满流则不存在欧拉回路;考虑反悔情况,若一条无向边对应的剩余容量为0,则说明该无向边反悔,将其反向
得到有向图后跑有向图欧拉回路即可。。。
#include<stdio.h>
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<math.h>
#include<string.h>
using namespace std;
const int N=10000,inf=1e9;
struct FLOW{
int p[N],nex[N],head[N],c[N],e;
int dp[N],s,t;
queue<int>q;
void add(int a,int b,int x){
p[++e]=b;
nex[e]=head[a];
head[a]=e;
c[e]=x;
p[++e]=a;
nex[e]=head[b];
head[b]=e;
c[e]=0;
}
int bfs(){
int i,u,v;
for(i=1;i<=t;i++) dp[i]=inf;
dp[s]=0;
for(q.push(s);q.size();q.pop()){
u=q.front();
for(i=head[u];i;i=nex[i]){
v=p[i];
if(c[i]&&dp[v]>dp[u]+1){
dp[v]=dp[u]+1;
q.push(v);
}
}
}
return dp[t]!=inf;
}
int dfs(int u,int f){
if(u==t||f==0) return f;
int i,v,k,sum=0;
for(i=head[u];i;i=nex[i]){
v=p[i];
if(dp[v]==dp[u]+1&&c[i]){
k=dfs(v,min(c[i],f-sum));
sum+=k;
c[i]-=k;
c[i^1]+=k;
if(sum==f) break;
}
}
if(sum==0) dp[u]=-1;
return sum;
}
int maxflow(){
int ans=0;
while(bfs()) ans+=dfs(s,inf);
return ans;
}
void init(){
e=1;
memset(head,0,sizeof(head));
}
}F;
int in[N],out[N],id[N];
struct E{
int a,b;
char s[5];
}A[N];
int ck(int n){
int i;
for(i=1;i<=n;i++) if((in[i]-out[i])%2) return 0;
return 1;
}
struct EULER{
int p[N],nex[N],head[N],vis[N],e;
vector<int>g;
void add(int a,int b){
p[++e]=b;
nex[e]=head[a];
head[a]=e;
}
void dfs(int u){
int v,now;
for(int &i=head[u];i;i=nex[i]){
v=p[i];
if(vis[i/2]==0){
vis[i/2]=1;
now=i;
dfs(v);
g.push_back(now);
}
}
}
void init(){
g.clear();
memset(head,0,sizeof(head));
memset(vis,0,sizeof(vis));
e=1;
}
}B;
int main(){
int i,n,a,b,t,m;
char s[10];
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++) in[i]=out[i]=0;
F.init();
for(i=1;i<=m;i++){
scanf("%d%d%s",&A[i].a,&A[i].b,A[i].s); //s为U为无向边,否则有向边
out[A[i].a]++;
in[A[i].b]++;
}
if(ck(n)==0) printf("No euler circuit exist\n");
else{
F.s=n+1;
F.t=n+2;
int sum=0,root;
for(i=1;i<=n;i++){
a=(out[i]-in[i])/2;
if(a>0) F.add(F.s,i,a);
else F.add(i,F.t,-a);
if(a>0) sum+=a;
}
for(i=1;i<=m;i++){
if(A[i].s[0]=='U'){
id[i]=F.e+1;
F.add(A[i].a,A[i].b,1);
}
}
sum-=F.maxflow();
if(sum) printf("No euler circuit exist\n");
else{
B.init();
for(i=1;i<=m;i++){
if(A[i].s[0]=='U'&&F.c[id[i]]==0) swap(A[i].a,A[i].b);
B.add(A[i].a,A[i].b);
B.e++;
root=A[i].a;
}
B.dfs(root);
if(B.g.size()!=m) printf("No euler circuit exist\n");
else{
printf("%d",root);
for(i=B.g.size()-1;i>=0;i--){
a=B.g[i];
printf(" %d",B.p[a]);
}
printf("\n");
}
}
}
printf("\n");
}
return 0;
}