BZOJ 2535 Plane 航空管制2
http://www.lydsy.com/JudgeOnline/problem.php?id=2535
思路:对于1,我们只需要每个点比前驱大就可以了,然后满足尽量优。
对于第二问,我们先求出这个点前驱有几个,记为ans,cnt=ans
每访问一个未访问的点,cnt++
然后对于后面的点从少往大排,若有k>ans,那么一定在我们当前处理这个点前面,ans++
若有k<=cnt,说明要i放在这个点的后面,因此ans=k+1
记得不要省方便add(read(),read()),好像会出错。
1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 struct node{ 7 int k,id; 8 }p[200005]; 9 int tot=0,go[200005],next[200005],first[200005]; 10 int A[200005],n,m,vis[200005],cnt; 11 int read(){ 12 int t=0,f=1;char ch=getchar(); 13 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 14 while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} 15 return t*f; 16 } 17 void insert(int x,int y){ 18 tot++; 19 go[tot]=y; 20 next[tot]=first[x]; 21 first[x]=tot; 22 } 23 void add(int x,int y){ 24 insert(x,y);insert(y,x); 25 } 26 void init(){ 27 n=read();m=read(); 28 for (int i=1;i<=n;i++) p[i].k=read(),p[i].id=i; 29 for (int i=1;i<=m;i++){ 30 int x=read(),y=read(); 31 add(x,y); 32 } 33 } 34 bool cmp(node q,node w){ 35 return q.k<w.k; 36 } 37 bool deal(int x){ 38 for (int i=first[x];i;i=next[i]){ 39 if (i&1){ 40 int pur=go[i]; 41 p[x].k=std::min(p[x].k,p[pur].k-1); 42 } 43 } 44 } 45 void solve1(){ 46 for (int j=1;j<=n;j++) 47 for (int i=1;i<=n;i++) 48 deal(i); 49 std::sort(p+1,p+1+n,cmp); 50 for (int i=1;i<n;i++) printf("%d ",p[i].id); 51 printf("%d\n",p[n].id); 52 } 53 int count(int x){ 54 int res=0;vis[x]=1; 55 for (int i=first[x];i;i=next[i]){ 56 int pur=go[i]; 57 if (!vis[pur]&&(i%2==0)){ 58 res+=count(pur); 59 } 60 } 61 return res+1; 62 } 63 void solve2(){ 64 for (int i=1;i<=n;i++){ 65 memset(vis,0,sizeof vis); 66 int ans=count(i); 67 cnt=ans; 68 for (int j=1;j<=n;j++) 69 if (!vis[p[j].id]){ 70 cnt++; 71 if (p[j].k<=ans) ans++; 72 else if (cnt>p[j].k) ans=p[j].k+1; 73 } 74 A[i]=ans; 75 } 76 for (int i=1;i<n;i++) printf("%d ",A[i]); 77 printf("%d\n",A[n]); 78 } 79 void work(){ 80 solve1(); 81 solve2(); 82 } 83 int main(){ 84 init(); 85 work(); 86 }