Wires CodeForces - 1250N(思维)

Polycarpus has a complex electronic device. The core of this device is a circuit board. The board has 109 contact points which are numbered from 1 to 109. Also there are n wires numbered from 1 to n, each connecting two distinct contact points on the board. An electric signal can pass between wires A and B if:
在这里插入图片描述
either both wires share the same contact point;
or there is a sequence of wires starting with A and ending with B, and each pair of adjacent wires in the sequence share a contact point.
The picture shows a circuit board with 5 wires. Contact points with numbers 2,5,7,8,10,13 are used. Here an electrical signal can pass from wire 2 to wire 3, but not to wire 1.
Currently the circuit board is broken. Polycarpus thinks that the board could be fixed if the wires were re-soldered so that a signal could pass between any pair of wires.

It takes 1 minute for Polycarpus to re-solder an end of a wire. I.e. it takes one minute to change one of the two contact points for a wire. Any contact point from range [1,109] can be used as a new contact point. A wire’s ends must always be soldered to distinct contact points. Both wire’s ends can be re-solded, but that will require two actions and will take 2 minutes in total.

Find the minimum amount of time Polycarpus needs to re-solder wires so that a signal can pass between any pair of wires. Also output an optimal sequence of wire re-soldering.

Input
The input contains one or several test cases. The first input line contains a single integer t — number of test cases. Then, t test cases follow.

The first line of each test case contains a single integer n (1≤n≤105) — the number of wires. The following n lines describe wires, each line containing two space-separated integers xi,yi (1≤xi,yi≤109, xi≠yi) — contact points connected by the i-th wire. A couple of contact points can be connected with more than one wire.

Sum of values of n across all test cases does not exceed 105.

Output
For each test case first print one line with a single integer k — the minimum number of minutes needed to re-solder wires so that a signal can pass between any pair of wires. In the following k lines print the description of re-solderings. Each re-soldering should be described by three integers wj,aj,bj (1≤wj≤n, 1≤aj,bj≤109). Such triple means that during the j-th re-soldering an end of the wj-th wire, which was soldered to contact point aj, becomes soldered to contact point bj instead. After each re-soldering of a wire it must connect two distinct contact points. If there are multiple optimal re-solderings, print any of them.

Example
Input
2
1
4 7
4
1 2
2 3
4 5
5 6
Output
0
1
2 3 5
这道题目代码写的又臭又长,所以大体看看思路,代码还是自己实现比较好。
思路:首先处理出连通块的数量,减一就是我们所需要连的线的数量。
我们将前面的连通块都链接到最后一个连通块上。如果这个连通块有度数为一的点,这个点就舍弃不要了。如果没有度数为一的点,那么我们不能随便找一个边连上,因为这条边有可能是割边,我是采用的“试”的方法,把这个连通块中的点挨个的试,只要发现不是割点,就说明这个链接这个点的边不是割边,那就舍弃这条边就可以了。
代码如下:

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int maxx=1e5+100;
struct node{
	int x,y;
}p[maxx];
struct edge{
	int to,next;
}e[maxx<<1];
struct Node{
	int x,y,z;
}ans[maxx<<1];
int head[maxx<<1],a[maxx<<1],deg[maxx<<1],vis[maxx<<1];
int n,tot;
map<int,bool> vio;
vector<int> pp[maxx<<1];

inline void init(int len)
{
	memset(head,-1,sizeof(head));
	tot=0;
	for(int i=0;i<=len+1;i++) deg[i]=vis[i]=0,pp[i].clear();
}
inline void add(int u,int v)
{
	e[tot].next=head[u],e[tot].to=v,head[u]=tot++;
}
inline void dfs(int u,int mk)
{
	vis[u]=mk;
	for(int i=head[u];i!=-1;i=e[i].next)
	{
		int to=e[i].to;
		if(vis[to]) continue;
		dfs(to,mk);
	}
}
inline int Dfs(int u,int &num)
{
	vio[u]=1;
	num++;
	for(int i=head[u];i!=-1;i=e[i].next)
	{
		int to=e[i].to;
		if(vio[to]) continue;
		Dfs(to,num);
	}
}
inline int check(int x)
{
	vio.clear();
	vio[x]=1;
	int uu;
	for(int i=0;i<pp[vis[x]].size();i++) 
	{
		if(pp[vis[x]][i]!=x) 
		{
			uu=pp[vis[x]][i];
			break;
		}
	}
	int num=0;
	Dfs(uu,num);
	return num==pp[vis[x]].size()-1;
}
inline int fcs(int u)
{
	for(int i=0;i<pp[u].size();i++)
	{
		if(check(pp[u][i])) return pp[u][i];
	}
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		int len=0;
		for(int i=1;i<=n;i++) scanf("%d%d",&p[i].x,&p[i].y),a[++len]=p[i].x,a[++len]=p[i].y;
		sort(a+1,a+1+len);
		len=unique(a+1,a+1+len)-a-1;
		init(len);
		int x,y;
		for(int i=1;i<=n;i++)
		{
			x=lower_bound(a+1,a+1+len,p[i].x)-a;
			y=lower_bound(a+1,a+1+len,p[i].y)-a;
			add(x,y);
			add(y,x);
			deg[x]++,deg[y]++;
		}
		int cnt=0;
		for(int i=1;i<=len;i++) if(vis[i]==0) dfs(i,++cnt);
		int zz;
		for(int i=1;i<=len;i++) pp[vis[i]].push_back(i);
		int cc=0,rr;
		map<int,int> mp;mp.clear();
		for(int i=1;i<=n;i++)
		{
			x=lower_bound(a+1,a+1+len,p[i].x)-a;
			if(vis[x]==cnt||mp[vis[x]]) continue;
			rr=-1;mp[vis[x]]=1;
			for(int j=0;j<pp[vis[x]].size();j++) 
			{
				if(deg[pp[vis[x]][j]]==1)
				{
					rr=pp[vis[x]][j];
					break;
				}
			}
			if(rr==-1) rr=fcs(vis[x]);
			for(int j=1;j<=n;j++)
			{
				if(p[j].x==a[rr]||p[j].y==a[rr])
				{
					ans[++cc].x=j;ans[cc].y=a[rr];ans[cc].z=a[pp[cnt][0]];
					break;
				}
			}
		}
		cout<<cnt-1<<endl;
		for(int i=1;i<=cc;i++) printf("%d %d %d\n",ans[i].x,ans[i].y,ans[i].z);
	}
	return 0;
}

努力加油a啊,(o)/~

发布了617 篇原创文章 · 获赞 64 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/starlet_kiss/article/details/105275663