题目:
题意:
现在有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;
}