Codeforces Round #22 (Div 2 only) C. System Administrator
問題概要
n個の頂点をm本の辺でつないだ、次の条件を満たすような無向グラフを作り、グラフを辺リスト表現で出力せよ。
- グラフの頂点は1〜nの番号をもつ。
- グラフは連結である。
- グラフから頂点vを取り除くと連結ではなくなる。
このようなグラフを作ることが不可能の場合-1を出力せよ。
3≤n≤10^5, m≤10^5を満たす
解法
頂点がn個で、条件を満たすグラフの辺の本数として可能な範囲を考える。
まず、連結であることからm≥n-1.
上限についてはvを取り除いた後にできる二つグラフの頂点の数をa,bとすれば
m≤C(a+1,2)+C(b+1,2)である。nを固定したときこれが最大になるのはa,bのどちらかが1のときである。
以上のような考察から、mが上の範囲にないときは-1を出力し,
あるときは1個の頂点をグループA,Aの1個とvを除いた残りの頂点をグループBとして、
まずvとA,Bの各頂点をつなぎ、残りは適当に数をあわせてBグループ内の頂点をつないで出力すればよい。
ソースコード
void run() { int n,m,v; cin>>n>>m>>v; if(!ok(n,m)) { cout<<-1<<endl; return; } vi g1,g2; int ng1=0,ng2=0; rep(i,n)if(i+1!=v) { if(ng1<1)g1.pb(i+1),ng1++; else g2.pb(i+1),ng2++; } rep(i,ng1)cout<<v<<" "<<g1[i]<<endl; rep(i,ng2)cout<<v<<" "<<g2[i]<<endl; m-=ng1+ng2; if(m>0)rep(i,ng1)rep(j,i) { cout<<g1[i]<<" "<<g1[j]<<endl; if(--m==0)return; } if(m>0)rep(i,ng2)rep(j,i) { cout<<g2[i]<<" "<<g2[j]<<endl; if(--m==0)return; } }