链接:点击打开链接
题意:n个点m条边的无向图,问是否满足将所有边变为有向后,每个点入度和出度的点不超过1
代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
struct node{
int to,next,cost;
}G[1000005];
int cnt,sign,deg[200005],head[200005];
void addedge(int u,int v){
G[cnt].to=v;
G[cnt].cost=0;
G[cnt].next=head[u];
head[u]=cnt++;
}
void dfs(int s){
int i,tmp,flag;
if(sign)
return;
for(i=head[s];i!=-1;i=G[i].next){
if(sign) //剪枝
return;
tmp=G[i].to;
flag=G[i].cost^G[i^1].cost; //判断这条无向边是否走过
if(flag)
continue;
head[s]=G[i].next; //走过的边就不再走了
G[i].cost=1;
if(deg[tmp]){ //遇到奇度点就不再搜索
sign=1;
deg[tmp]=0;
return;
}
if(!sign)
dfs(tmp);
}
return;
}
int main(){ //需要知道三个性质
int n,m,t,i,j,u,v; //1.一个图奇度点有偶数个
scanf("%d",&t); //2.只含有两个奇度点的无向图含有欧拉路径
while(t--){ //3.不含奇度点的无向图含有欧拉回路
cnt=0; //根据这三个性质可以得出一个图必定可以拆成一个
scanf("%d%d",&n,&m); //欧拉回路和许多欧拉路径,因此奇度点两两配对
for(i=1;i<=n;i++)
deg[i]=0,head[i]=-1;
for(i=0;i<m;i++){
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
deg[u]^=1,deg[v]^=1;
}
for(i=1;i<=n;i++){
if(deg[i]){ //奇度点进行欧拉路径的搜索
sign=deg[i]=0;
dfs(i);
}
}
sign=0;
for(i=1;i<=n;i++)
if(head[i]!=-1) //不是孤立点的点i进行欧拉回路的搜索
dfs(i);
for(i=0;i<cnt;i+=2)
printf("%d\n",G[i].cost);
}
return 0;
}