POJ 1438 混合图定定向为强连通图 双连通

题意:

给定n个点 m条边 (点标从1开始)

下面m行表示边 u v k (k=1为单向,k=2为双向)

问:

把尽可能多的无向边定向使得最终图保持强连通的性质(任意两点可达)

答案保证有解。

输出所有无向边最终的情况

u v k (k = 2表示不定向 , k = 1表示定向为 u->v)

思路:

1、tarjan:由于图中既有有向边,又有无向边,那么先把有向边视为无向,用双连通求桥,直接输出桥然后删掉该边即可(因为题目保证有解,所以桥一定是无向边)

2、那么图中就只剩下一个个连通块,对于任意连通块(当前是当作边全为无向)我们必然能把所有无向边定向。因为要使得定向后依旧强连通,所以对于任意点u的low[u]值一定<=dfn[u].

1、当前遍历的是树边->若当前边是无向边:假如不满足该等式,则将边反向,若满足则无向边方向正确(定向后直接输出并删边)

2、当前遍历的是后向边-> 容易确定若为无向边就让这边成为后向边。

 

 

 

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<math.h>
#include<vector>
#define N 2005
using namespace std;

int n,m;//n个点 m条边
int low[N],dfn[N],tarjin_time;
bool map[N][N], flag[N][N];
void add(int u,int v,bool bid)
{
	map[u][v] = true; flag[u][v] = bid;
}
void tarjin(int u,int pre)
{
	low[u]=dfn[u]= ++tarjin_time;
	for(int v = 1; v <= n; v++)
	{
		if(v == pre || !flag[u][v])continue;
		if(!dfn[v])
		{
			tarjin(v,u);
			if(low[u]>low[v])low[u]=low[v];
			if(low[v]>dfn[u])
			{ printf("%d %d 2\n", u, v); flag[u][v] = flag[v][u] = false; continue;}
		}
		else if(low[u]>dfn[v])low[u]=dfn[v];
	}
}
void find_edgecut()
{
	memset(dfn,0,sizeof(dfn));
	tarjin_time=1;
	for(int i=1;i<=n;i++)if(!dfn[i])tarjin(i,i);
}


void init(){
	for(int i = 1; i <= n; i++)memset(map[i], 0, sizeof(map[i])), memset(flag[i], 0, sizeof(flag[i]));
}

void dfs(int u,int pre)
{
	low[u]=dfn[u]= ++tarjin_time;
	for(int v = 1; v <= n; v++)
	{
		if(v == pre || !flag[u][v])continue;
		if(!dfn[v])
		{
			dfs(v,u);
			if(low[u]>low[v])low[u]=low[v];
			if(flag[v][u])
			{
			if(low[v]>dfn[u])
			{ printf("%d %d 1\n", v, u); flag[u][v] = false;}
			else
			{ printf("%d %d 1\n", u, v); flag[v][u] = false;}
			}
		}
		else 
		{
			if(flag[v][u])printf("%d %d 1\n", u, v);
			flag[u][v] = false;
			low[u] = min(low[u], dfn[v]);
		}
	}
}
int main(){
	int u, v, i, k;
	while(~scanf("%d %d",&n,&m)){
		init();
		while(m--){
			scanf("%d %d %d", &u, &v, &k);
			add(u, v, 1); add(v, u, k==2);			
		}
		find_edgecut();
		memset(dfn, 0, sizeof(dfn));tarjin_time = 0;
		for(i = 1; i <= n; i++)if(!dfn[i])dfs(i, 0);
	}
	return 0;
}
/*
4 4
4 1 1
4 2 2
1 2 1
1 3 2

*/


 

POJ 1438 混合图定定向为强连通图 双连通

上一篇:Photoshop为室内人物图片调制出低饱和日系色效果


下一篇:minio文件服务(java)