uvalive3523非主流的代码!!求点双连通分量

刘汝佳的代码感觉拖泥带水的啊!!!只有自己撸一个了!!!
此题先开始让互相不讨厌的骑士连边然后就是求点连通分量拉,在点联通分量上的点都是阔能在一个圆桌上的,不过要注意的是点联通分量必须是奇数的,题目要求。。烦~~
//如果有重边弄一个标价变量k时就好了k==0时continue k>=1时不continue;
//这个程序还不能处理只有一个点的连通块如果需要计数这种情况的话先初始化让每个点都成一个连通块最后没和其他点在一起的点就单独成一个
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<stack>;
using namespace std;
struct edgee
{
	int to,from;
};
int n, m;
int map[1050][1050], first[1050], nextt[2000020];
int edgetot;
edgee edge[2000020];
int deep;
int dfn[1050], low[1050];
stack<edgee>stackk;
vector<int>bcc[1050];
int bccamount;
void addedge(int from, int to)
{
	edge[edgetot].to = to;
	edge[edgetot].from = from;
	nextt[edgetot] = first[from];
	first[from] = edgetot;
	edgetot++;
	edge[edgetot].to = from;
	edge[edgetot].from = to;
	nextt[edgetot] = first[to];
	first[to] = edgetot;
	edgetot++;
}
void dfs(int num,int fa)
{
	dfn[num] = low[num] = deep++;
	for (int i = first[num]; i != -1; i = nextt[i])
	{
		edgee e = edge[i]; int to = e.to;
		if (dfn[to] == 0)
		{
			stackk.push(e);
			dfs(to,num);
			low[num] = min(low[num], low[to]);
			if (low[to] >= dfn[num])
			{
				edgee ee = stackk.top();//注意用的是栈来收集的边不是队列或者其他什么的。。。还有搜集的是边不是点为什么。。因为一个点阔以在多个点联通分量
				while (ee.from!=num&&ee.to!=to)
				{
					int too = ee.to;
					stackk.pop();
					bcc[bccamount].push_back(too);
					ee = stackk.top();
				}
				if(low[to]==dfn[num])bcc[bccamount].push_back(num), bcc[bccamount].push_back(to);//注意这两组数据 1->2 2->3 3->4 4->2和 1->2 2->3 3->1 3->4 4->5 5->6 6->4都是无向边
				stackk.pop();                                                                     //这样写就是为了区别这些情况,当然如果只有一个点确实不会进桶不过由于先开始初始化了的
				bccamount++;                                                                      //所以不存在拉拉
			}
		}
		else
		{
			if (to != fa)
				low[num] = min(low[num], dfn[to]);//由于是无向图所以是不会有横向边的。。。
		}
	}
}
int show[2000],color[2000],countt[2000];
bool searchh(int num, int kind)
{
	color[num] = 3 - kind;
	for (int i = first[num]; i != -1; i = nextt[i])
	{
		int to = edge[i].to; if (show[to] == 0)continue;
		if (color[to] == color[num])return false;
		if (color[to] != 0)continue;
		int kk = searchh(to, color[num]); if (!kk)return false;
	}
	return true;
}
void getbitwo()
{
	for (int i = 0; i < bccamount; i++)
	{
		for (int j = 0; j < bcc[i].size(); j++)
		{
			int to = bcc[i][j]; show[to] = 1; color[to] = 0;
		}
		bool isright = false;
		if (!bcc[i].empty())
		 isright= searchh(bcc[i][0],1);
			for (int j = 0; j < bcc[i].size(); j++)
			{
				int  to = bcc[i][j]; show[to] = 0; color[to] = 0;
				if (!isright)countt[to] = 1;
			}
	}
}

int main()
{
	while (scanf("%d%d", &n, &m) && n&&m)
	{
		while (!stackk.empty())stackk.pop();
		edgetot = 0; deep = 0; bccamount = 0;
		for (int i = 1; i <= n; i++)
		{
			first[i] = -1; dfn[i] = low[i] = 0; bcc[i].clear(); countt[i] = 0;
			for (int j = 1; j <= n; j++)
				map[i][j] = 0;
		}
		for (int i = 0; i < m; i++)
		{
			int a, b;
			scanf("%d%d", &a, &b);
			map[a][b] = map[b][a] = 1;
		}
		for (int i = 1; i <= n; i++)
			for (int j = i + 1; j <= n; j++)
			{
			if (!map[i][j])addedge(i, j);//由于调试的需要现在我先改一下以后改回来!!!!!
			}
		for (int i = 1; i <= n; i++)
		{
			if (dfn[i] == 0)
				dfs(i, -1);
		}
		getbitwo();
		int ans = n;
		for (int i = 1; i <= n; i++)
			if (countt[i])ans--;
		printf("%d\n", ans);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值