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

          题目:

                  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;
}


你可能感兴趣的:(CERC2012 j - Conservation 有条件的维护拓扑序列)