概述
题目链接:
http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1793
题目大意:
一辆公交车,上面M个座位,N个人(M<=N<=1000),每个人只有在Ci也上车的情况下才上车。问最多上车几人。
题目思路:
【动态规划】【缩点】
首先这是一张N个点N条边的有向图。如果J在I也上车的情况下才上车则连一条I到J的边。这样每个点入度最多为1.
这张图有可能有环,所以先缩点,缩完点之后每个环不会有入边,且一定是一个子树的根节点。这样原来的有环的图就变成若干颗树。
而每个树都有取值的上下界[A,B]A为环的大小,B为这棵树的大小(只取环上的人上车,或者再一个一个加上链上的人)
那么问题就变成K个有取值范围的背包。问容量不超过M最大能取到多少值。
三方枚举,f[i][j]表示前I个容量为J的状态能否达到,根据当前取值范围[A,B]转移。
1 // 2 //by coolxxx 3 //#include<bits/stdc++.h> 4 #include<iostream> 5 #include<algorithm> 6 #include<string> 7 #include<iomanip> 8 #include<map> 9 #include<stack> 10 #include<queue> 11 #include<set> 12 #include<bitset> 13 #include<memory.h> 14 #include<time.h> 15 #include<stdio.h> 16 #include<stdlib.h> 17 #include<string.h> 18 //#include<stdbool.h> 19 #include<math.h> 20 #define min(a,b) ((a)<(b)?(a):(b)) 21 #define max(a,b) ((a)>(b)?(a):(b)) 22 #define abs(a) ((a)>0?(a):(-(a))) 23 #define lowbit(a) (a&(-a)) 24 #define sqr(a) ((a)*(a)) 25 #define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b)) 26 #define mem(a,b) memset(a,b,sizeof(a)) 27 #define eps (1e-8) 28 #define J 10 29 #define mod 1000000007 30 #define MAX 0x7f7f7f7f 31 #define PI 3.14159265358979323 32 #define N 1004 33 using namespace std; 34 typedef long long LL; 35 int cas,cass; 36 int n,m,lll,ans; 37 int fa[N],pre[N],num[N],e[N],t[N],last[N],in[N],q[N]; 38 bool f[N][N]; 39 bool u[N]; 40 struct xxx 41 { 42 int next,to; 43 }a[N]; 44 void cover(int x) 45 { 46 int i=e[x]; 47 fa[x]=x; 48 num[x]=1; 49 while(i!=x) 50 { 51 num[x]++; 52 num[i]=0; 53 fa[i]=x; 54 i=e[i]; 55 } 56 } 57 void dfs(int u) 58 { 59 if(t[u]) 60 { 61 if(t[u]>cass)cover(u); 62 return; 63 } 64 t[u]=++cas; 65 //fa[u]=e[u]; 66 dfs(e[u]); 67 } 68 void add(int x,int y) 69 { 70 a[++lll].next=last[x]; 71 a[lll].to=y; 72 last[x]=lll; 73 } 74 int work(int now) 75 { 76 int i,to,sum=0; 77 for(i=last[now];i;i=a[i].next) 78 { 79 to=a[i].to; 80 sum+=work(to); 81 } 82 return sum+num[now]; 83 } 84 void spfa() 85 { 86 int i,l=0,r=0,now,to; 87 mem(u,0);cas=0; 88 for(i=1;i<=n;i++) 89 if(!in[i] && num[i])q[++cas]=i,pre[i]=work(i); 90 } 91 92 int main() 93 { 94 #ifndef ONLINE_JUDGE 95 // freopen("1.txt","r",stdin); 96 // freopen("2.txt","w",stdout); 97 #endif 98 int i,j,k; 99 int x,y,z; 100 // for(scanf("%d",&cass);cass;cass--) 101 // for(scanf("%d",&cas),cass=1;cass<=cas;cass++) 102 // while(~scanf("%s",s+1)) 103 while(~scanf("%d",&n)) 104 { 105 lll=0;mem(num,0);mem(t,0);mem(in,0);mem(last,0);mem(pre,0);mem(f,0); 106 scanf("%d",&m); 107 for(i=1;i<=n;i++) 108 { 109 scanf("%d",&e[i]); 110 num[i]=1;fa[i]=i; 111 } 112 cas=0; 113 for(i=1;i<=n;i++) 114 { 115 if(t[i])continue; 116 cass=cas; 117 dfs(i); 118 } 119 for(i=1;i<=n;i++) 120 { 121 if(num[i]==0 || fa[e[i]]==i)continue; 122 add(fa[e[i]],i); 123 in[i]++; 124 } 125 spfa(); 126 f[0][0]=1; 127 for(i=1;i<=cas;i++) 128 { 129 x=q[i];y=q[i-1]; 130 for(j=0;j<=m;j++) 131 { 132 f[x][j]|=f[y][j]; 133 for(k=num[x];k<=pre[x] && j+k<=m;k++) 134 f[x][j+k]|=f[y][j]; 135 } 136 } 137 x=q[cas]; 138 for(i=m;i;i--) 139 if(f[x][i])break; 140 printf("%dn",i); 141 } 142 return 0; 143 } 144 /* 145 // 146 147 // 148 */
转载于:https://www.cnblogs.com/Coolxxx/p/5827408.html
最后
以上就是野性睫毛为你收集整理的【动态规划】【缩点】NCPC 2014 G Outing的全部内容,希望文章能够帮你解决【动态规划】【缩点】NCPC 2014 G Outing所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复