CERC2012 j - Conservation 有条件的维护拓扑序列

来源:互联网 发布:欧洲工商管理学院 知乎 编辑:程序博客网 时间:2024/06/05 08:11

          题目:

                  Click here

          题意:

                  现在有1,2两个舞台...告诉每个节目要在哪个舞台演出...再告诉一些舞台的演出先后关系..问如何安排让换舞台的次数最少...

          题解:

                  根据先后关系可以构造有向图....容易发现安排的顺序是拓扑序列..那如何让交换次数最少呢?这就需要在做拓扑序列时用贪心的思想使得每次连续相同的最多..注意的是第一次...从1开始和从2开始都要尝试...


Program:

#include<stdio.h> #include<string.h> #include<cmath>#define pi acos(-1.0)#define MAXN 100005#define ll int#define MAXM 1000005#define oo 1<<29  using namespace std;ll st[MAXN],ne,edge[MAXM][2],_next[MAXN],d[MAXN],dd[MAXN],Q1[MAXN],Q2[MAXN],Q1num,Q2num;   int count(ll Q1num,ll Q2num,ll k){      ll ans=0,u,v,t;      while (Q1num || Q2num)      {               if (k==1)               {                      if (!Q1num) ans++,k=2,u=Q2[Q2num--];                              else u=Q1[Q1num--];               }else               {                      if (!Q2num) ans++,k=1,u=Q1[Q1num--];                              else u=Q2[Q2num--];                }               for (t=_next[u];t;t=edge[t][1])               {                       v=edge[t][0];                      d[v]--;                      if (!d[v])                       {                             if (st[v]==1) Q1[++Q1num]=v;                                     else  Q2[++Q2num]=v;                      }               }       }       return ans;}int main(){       ll cases,n,m,i,u,v,t,k,ans,temp;          scanf("%d",&cases);       while (cases--)       {                scanf("%d%d",&n,&m);               ne=0;               for (i=1;i<=n;i++) scanf("%d",&st[i]),_next[i]=d[i]=0;                while (m--)               {                       scanf("%d%d",&u,&v);                       d[v]++;                        edge[++ne][1]=_next[u];                       _next[u]=ne,edge[ne][0]=v;               }               for (i=1;i<=n;i++) dd[i]=d[i];               ans=Q1num=Q2num=0;               for (i=1;i<=n;i++)                  if (!d[i])                   {                       if (st[i]==1) Q1[++Q1num]=i;                                else Q2[++Q2num]=i;                  }                ans=oo;               if (Q1num) ans=count(Q1num,Q2num,1);               Q1num=Q2num=0;               for (i=1;i<=n;i++) d[i]=dd[i];               for (i=1;i<=n;i++)                  if (!d[i])                   {                       if (st[i]==1) Q1[++Q1num]=i;                                else Q2[++Q2num]=i;                  }                               if (Q2num)                {                      temp=count(Q1num,Q2num,2);                      if (temp<ans) ans=temp;               }               printf("%d\n",ans);       }       return 0;}


原创粉丝点击