hdu 7135 Bigraph Extension
分析:
-
构造一个 2 n 2n 2n 的环(就很难想到)
-
两个集合之间连边,且要求从 A A A 集合任意一点到 B B B 集合任意一点(可能会有多条边),要求最长的边 l e n > n len>n len>n
-
考虑将这个二分图展开来看,会是一个连通块,且一条边上的两端点分别属于两个集合
要使 l e n > n len>n len>n,那这个连通块必然是由多个环组成的(链上肯定存在 l e n < = n len<=n len<=n 的情况)
又要使添的的边最少,所以构造一个 2 n 2n 2n 的环即可
-
具体构图方法:并查集 + + + 环的性质(每个点的度都为 2 2 2 )
-
按字典序的话,就从点 1 1 1 ~ n n n 逐一构造即可
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int du[N],f[N];
int fd(int k) { return f[k]==k ? k : f[k]=fd(f[k]); }
vector <pair<int,int> > g;
signed main()
{
ios_base::sync_with_stdio(0);
int T;
cin>>T;
while(T--)
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++) du[i]=du[i+n]=0, f[i]=i, f[i+n]=i+n;
g.clear();
for(int i=1;i<=m;i++)
{
int u,v;
cin>>u>>v;
du[u]++;
du[v+n]++;
f[v+n]=u;
}
int st=1;
for(int i=1;i<=n;i++)
{
for(int j=st;j<=n;j++)
{
if(du[j+n]<2)
{
int x=fd(i), y=fd(j+n);
if(x!=y)
{
du[i]++; du[j+n]++;
f[y]=x;
g.push_back({i,j});
}
}
if(du[i]==2) break;
if(du[st+n]==2) st++;
}
}
for(int i=1;i<=n;i++)
{
if(du[i+n]==1)
{
g.push_back({n,i});
break;
}
}
cout<<g.size()<<endl;
for(auto ans : g) cout<<ans.first<<' '<<ans.second<<endl;
}
return 0;
}