Codeforces 134C Swaps (bfs+优先队列)【模板】

来源:互联网 发布:电脑监控软件破解 编辑:程序博客网 时间:2024/05/17 09:29

There are n players sitting at a round table. All of them have s cards of n colors in total. Besides, initially the first person had cards of only the first color, the second one had cards of only the second color and so on. They can swap the cards by the following rules:

  • as the players swap, a player can give a card of his color only;
  • a player can't accept a card of a color he already has (particularly, he can't take cards of his color, no matter whether he has given out all of them or not);
  • during one swap a pair of people swaps cards (each person gives one card and takes one card).

The aim of all n people is as follows: each of them should give out all the cards he had initially (that is, all cards of his color). Your task is to denote whether such sequence of swaps is possible. If the answer is positive, you should list all the swaps.

Input

The first line contains integers n (1 ≤ n ≤ 200000) and s (1 ≤ s ≤ 200000). The second line contains n numbers, the i-th number stands for how many cards the i-th player has by the moment the game starts. It is possible that a player has no cards initially.

Output

On the first line print "No" if such sequence of swaps is impossible. Otherwise, print "Yes". If the answer is positive, next print number k — the number of the swaps. Then on k lines describe the swaps by pairs of indices of the swapping players. Print the swaps and the numbers of the swaps in any order.

Example
Input
4 82 2 2 2
Output
Yes44 34 21 31 2
Input
6 121 1 2 2 3 3
Output
Yes66 56 46 35 45 32 1
Input
5 50 0 0 0 5
Output
No

 【题解】

 大致题意:n个人一起玩游戏,游戏的规则:

1、每次只能交换一张卡片;

2、每个人都不能再获取与手中牌颜色一样的牌;

初始时有可能有人手中没有牌;

要完成这个游戏,需要所有人把自己手中原来的牌在给定的次数中都换出去,如果存在这种换法,则输出yes,并且输出换牌步骤,否则输出no;


解法:

 因为换牌一次是两张,所以s不可能是奇数,,所以如果如果s%2==1,那么一定是不可能的;

 如果出现牌大于总人数的,直接pass;

剩下的就要用bfs搜索了,因为每次只用与最大的那个来换,所以用优先队列保存下来,每次取最大的来换,知道队列为空。

再用个结构体保存每次交换的两张牌的id就好。

下面附上AC代码:

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<math.h>#include<stack>#include<queue>using namespace std;const int N=200000+10;const int inf=0x3f3f3f3f;int m,n,a[N];struct Node{    int val;    int id;    bool operator < (Node a)const//优先队列    {        return val<a.val;    }}node[N];struct no//保存交换的牌id{    int x,y;}ans[N];int main(){    int x;    Node st,ed;    priority_queue<Node>q;    while(~scanf("%d%d",&m,&n))    {        int tag=1;        while(!q.empty()) q.pop();        for(int i=1;i<=m;++i)        {            scanf("%d",&x);            if(x>=m) tag=0;//如果牌的大小超出了人数  直接pass;            st.val=x;            st.id=i;            if(st.val>0) q.push(st);//满足条件  加入队列        }        if(!tag||n%2)//不符合        {            printf("No\n");            continue;        }        int cnt=0;        for(int i=1;;++i)        {            if(q.empty()) break;            st=q.top();            q.pop();            //注意这里取出来的st一定是队列中val值最大的;            if(q.size()<st.val)//队列的中最大的牌的数比总人数还多,直接pass;            {                tag=0;                break;            }            for(int j=0;j<st.val;++j)            {                ed=q.top();                q.pop();                node[j].id=ed.id;                node[j].val=ed.val;                node[j].val--;                ans[cnt].x=st.id;//记录交换前后                ans[cnt++].y=node[j].id;            }            for(int j=0;j<st.val;++j)                if(node[j].val>0)                    q.push(node[j]);//还有未交换的  继续加入队列        }        if(!tag)        {            puts("No");            continue;        }        puts("Yes");        printf("%d\n",n/2);//交换回合数        for(int i=0;i<cnt;++i)            printf("%d %d\n",ans[i].x,ans[i].y);    }    return 0;}




原创粉丝点击