首页 > 代码库 > 【动态规划】【缩点】NCPC 2014 G Outing
【动态规划】【缩点】NCPC 2014 G Outing
题目链接:
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("%d\n",i);141 }142 return 0;143 }144 /*145 //146 147 //148 */
【动态规划】【缩点】NCPC 2014 G Outing
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。