zoukankan      html  css  js  c++  java
  • 【动态规划】【缩点】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
    ",i);
    141     }
    142     return 0;
    143 }
    144 /*
    145 //
    146 
    147 //
    148 */
    View Code
  • 相关阅读:
    jsp页面间传递参数 中文乱码问题(zz)
    java 生成xml
    java dom4j 解析xml
    生成不重复的32为随机码
    [HYSBZ
    七夕祭
    [CF741D] Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
    Baltic2014 sequence
    [洛谷P2459] SDOI2011 消耗战
    [洛谷P4172] WC2006 水管局长
  • 原文地址:https://www.cnblogs.com/Coolxxx/p/5827408.html
Copyright © 2011-2022 走看看