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)/~