题目:
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; }