Codeforces Round #611 (Div. 3) C

There are nn friends who want to give gifts for the New Year to each other. Each friend should give exactly one gift and receive exactly one gift. The friend cannot give the gift to himself.

For each friend the value fifi is known: it is either fi=0fi=0 if the ii-th friend doesn't know whom he wants to give the gift to or 1fin1≤fi≤n if the ii-th friend wants to give the gift to the friend fifi.

You want to fill in the unknown values (fi=0fi=0) in such a way that each friend gives exactly one gift and receives exactly one gift and there is no friend who gives the gift to himself. It is guaranteed that the initial information isn't contradictory.

If there are several answers, you can print any.

大意是有n个人相互给礼物(限定一个人只能收到一份,赠送一份),已知其中一部分人希望把礼物送给谁,要求补全这个关系图,只需要输出任何一种可能的情况。其中不能自己送给自己礼物。
自己的暴力做法是:将所有人分成三类。第一类:有送有收。第二类:有送无收。第三类:无送有收。第四类:无送无收。
首先建立一个优先队列用于输出,第一类已经彻底明确了的直接丢进去。易知第二类和第三类人数应该是一样的,这时候讨论第四类:
1.若第四类人数为0:
只需要将第二类的收和第三类的送对应起来。一一对应即可。
2.若第四类人数为1:
第二类第三类前面n-1对一一对应,最后一对之间插一个唯一的第四类。(因为要求不能自己送自己)。
3.第四类人数大于1:
第四类内部对应即可,内部构成一个环。
#include<bits/stdc++.h>
using namespace std;
int n;
struct point
{
 int num;
 int to;
 int from;
}f[200005];
bool operator<(point a, point b){ return a.num>b.num ;}
priority_queue<point> q;
vector<point> v1,v2,v3;//v1仅有from v2仅有to v3双无
int main()
{
 cin>>n;
 int i;
 for(i=1;i<=n;i++)
 {
  f[i].num=i;
  f[i].to=0;
  f[i].from=0;
 }
 for(i=1;i<=n;i++)
 {
  int temp;
  scanf("%d",&temp);
  f[i].to=temp;
  f[temp].from=i;
 }
 for(i=1;i<=n;i++)
 {
  if(f[i].from!=0&&f[i].to!=0)
  {
   q.push(f[i]);
  }
  else if(f[i].from==0&&f[i].to!=0)
  {
   v2.push_back(f[i]);
  }
  else if(f[i].from!=0&&f[i].to==0)
  {
   v1.push_back(f[i]);
  }
  else
  {
   v3.push_back(f[i]);
  }
 } 
//cout<<v1.size()<<' '<<v2.size()<<' '<<v3.size()<<' '<<q.size()<<endl;
if(v3.size()!=1)
{
 for(i=0;i<v2.size();i++)
 {
  v2[i].from=v1[i].num;
  v1[i].to=v2[i].num;
  q.push(v1[i]);
  q.push(v2[i]);
 }
 if(v3.size()==0)goto label;
 for(i=0;i<v3.size()-1;i++)//注意 不能自己给自己
 {
  v3[i].to=v3[i+1].num;
  q.push(v3[i]); 
  
 }
 v3[v3.size()-1].to=v3[0].num;
 q.push(v3[v3.size()-1]);
}
else
{
 for(i=0;i<v2.size()-1;i++)
 {
  v2[i].from=v1[i].num;
  v1[i].to=v2[i].num;
  q.push(v1[i]);
  q.push(v2[i]);
 }
 v2[v2.size()-1].from=v3[0].num;
 v1[v2.size()-1].to=v3[0].num;
 v3[0].to=v2[v2.size()-1].num;
 q.push(v1[v2.size()-1]);
 q.push(v2[v2.size()-1]);
 q.push(v3[0]);
 
}
 label:;
 while(!q.empty())
 {
  point temp=q.top();
  cout<<temp.to<<' ';
  q.pop();
 }
 return 0;
 }

猜你喜欢

转载自www.cnblogs.com/lipoicyclic/p/12221310.html