您的位置:首页 > 编程语言 > C语言/C++

【DFS】CODE[VS] 1535 封锁阳光大学(二分图DFS染色)

2016-10-30 11:09 477 查看
点击进入异世界

这个题,题意是给图染色判断是否为二分图

什么事二分图呢

顾名思义是可以将一个图中的点分为两个集合的图

这道题既可以用DFS也可以用BFS,先写下DFS的做法(比我写的BFS快一些)

二分图满足一个性质:不存在拥有奇数条边的环。如果存在则不是二分图因为,在二分图定义中,同属一个集合的点互相之间是没有连边的,若存在奇数环,则说明同集合点一定有连边。

如下图所示:

当有环且环上边数为偶数时

同集合点是没有连边的,也就是说一条边的两端点一定所属集合不同



当有环且环上边数为奇数时

左边点集中有两点连边,该边的两端点所属集合相同



二分图染色,就是将一个图按照二分图的规则对图中的点进行划分,若可以完成染色则说明该图是二分图

回到题目,题目实际上就是让我们进行二分图染色看是不是二分图

定义sum[1]是“黑色”,sum[2]是“白色”,在搜索每个连通子图(数据可能有的子图互相之间不连通)的时候,初始化搜索的第一个点为sum[1];

开始枚举,如果这个点没有遍历到则取与他父节点相反的颜色

若这个图遍历过,则判断其与其父节点的颜色是否相同,若相同则输出“Impossible”

这个题打了好几份代码,只有一份能AC,其余的都50分,这里附上两份

第一个打傻了的DFS+Trajan(50分)

当时混淆了双连通和连通,然后就没有与然后了….居然还能过5个点orz(垃圾代码,注释懒得删了)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <stack>

const int maxn = 120100;

using namespace std;

int tot;
int n,m;
int ans;
int qlt[maxn];
int head[maxn];
int color[maxn];
bool motherfucker;
bool vis[maxn];

struct node{
int f,t,next;
}e[maxn << 1];

inline void build(int x,int y)
{
//cout<<"------------------------------------"<<endl;
tot++;
//cout<<"head_after of "<<x<<" : "<<head[x]<<endl;
e[tot].f = x;
e[tot].t = y;
//cout<<tot<<" to : "<<e[tot].t<<endl;
e[tot].next = head[x];
//cout<<tot<<" next : "<<e[tot].next<<endl;
head[x] = tot;
//cout<<"head_fin of "<<x<<" : "<<head[x]<<endl;
//cout<<"------------------------------------"<<endl;
}

inline void dfs(int w,int muy1)
{
//cout<<"当前的w为"<<w<<"muy1为"<<muy1<<endl;
//cout<<"ans_after: "<<ans<<endl;
//cout<<"color of "<<w<<" is "<<color[w]<<endl;
//cout<<"motherfucker: "<<motherfucker<<endl;
ans = max(ans , muy1);
//cout<<"ans_fin: "<<ans<<endl;
//cout<<"head of "<<w<<" is "<<head[w]<<endl;
for(int i = head[w];i;i = e[i].next)
{
//cout<<"i----> "<<i<<endl;
//cout<<"colorw of "<<w<<" : "<<color[w]<<endl;
//cout<<"color of "<<e[i].t<<" : "<<color[e[i].t]<<endl;
int cmuy = muy1;
if(color[e[i].t] == 0)
{
if(color[w] == 1&&vis[e[i].t] != 1)
color[e[i].t] = 2;
if(color[w] == 2&&vis[e[i].t] != 1)
{
muy1++;
color[e[i].t] = 1;
}
dfs(e[i].t,muy1);
muy1 = cmuy;
}
else if(color[w] == color[e[i].t])
{
//cout<<color[w]<<" "<<color[e[i].t]<<endl;
motherfucker = 1;
//cout<<"now of motherfucker : "<<motherfucker<<endl;
}
}
}

int lowlink[maxn],sccno[maxn],clockw,cnt;

stack<int >s;

void tj(int u)
{
cout<<u<<endl;
qlt[u] = lowlink[u] = ++clockw;
cout<<"lowlink of "<<u<<" "<<lowlink[u]<<endl;
s.push(u);
cout<<"stack : "<<s.top()<<endl;
for(int i = head[u];i;i = e[i].next)
{
int v = e[i].t;
if(!qlt[v])
{
tj(v);
lowlink[u] = min(lowlink[u],lowlink[v]);
}
else if(!sccno[v])
{
lowlink[u] = min(lowlink[u],qlt[v]);
}
}
if(lowlink[u] == qlt[u])
{
cnt++;
for(;;)
{
int x = s.top();
s.pop();
sccno[x] = cnt;
if(x == u||s.empty())
break;
}
}
}

void find_scc(int xx)
{
clockw = cnt = 0;
memset(sccno,0,sizeof(sccno));
memset(qlt,0,sizeof(qlt));
for(int i = 1;i <= xx;i++)
{
if(!qlt[i])
tj(i);
}
}

bool cntused[maxn];

int main()
{
memset(color,0,sizeof(color));
scanf("%d%d",&n,&m);
for(int i = 1;i <= m;i++)
{
int aa,bb;
scanf("%d%d",&aa,&bb);
build(aa,bb);
build(bb,aa);
}
vis[1] = 1;
color[1] = 1;
find_scc(n);
for(int i = 1;i <= n;i++)
{
if(cntused[sccno[i]] == 0)
{
cntused[sccno[i]] = 1;
dfs(i,1);
}
if(cntused[sccno[i]] == 1)
continue;
}
if(motherfucker == 1)
printf("Impossible\n");
//cout<<"fuckyou"<<endl;
if(motherfucker == 0)
{
int dc = n-ans;
if(ans > dc)
{
for(int i = 1;i <= n;i++)
{
if(head[i] == 0)
dc++;
}
printf("%d\n",dc);
}
else
{
for(int i = 1;i <= n;i++)
{
if(head[i] == 0)
ans++;
}
printf("%d\n",ans);
}

}
return 0;
}


第二份是”极为正常”的DFS,要从1for到n,如果这个点没到过,就DFS递归调用

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

const int maxn = 10010;

using namespace std;

int tot;
int ans;
int n,m;
int color[maxn];
int head[maxn];
int sum[3];
bool vis[maxn];

struct node{
int f;
int t;
int next;
}e[maxn << 1];

inline void build(int ff,int tt)
{
tot++;
e[tot].f = ff;
e[tot].t = tt;
e[tot].next = head[ff];
head[ff] = tot;
}

inline bool dfs(int x,int cnt)
{
vis[x] = 1;
color[x] = cnt;
sum[cnt]++;
for(int i = head[x];i;i = e[i].next)
{
int u = e[i].t;
if(vis[u] == 1)
{
if(color[x] == color[u])
return false;
}
else
{
if(color[x] == 1)
dfs(u,2);
if(color[x] == 2)
dfs(u,1);
}
}
return true;
}

int main()
{
scanf("%d%d",&n,&m);
for(int i = 1;i <= m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
build(a,b);
build(b,a);
}
for(int i = 1;i <=n;i++)
{
sum[1] = sum[2] = 0;
if(vis[i] == 0)
{

if(dfs(i,1) == false)
{
printf("Impossible\n");
return 0;
}
ans += min(sum[1],sum[2]);
}
}
printf("%d\n",ans);
return 0;
}


THE END

By Peacefuldoge

http://blog.csdn.net/loi_peacefuldog
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息