码迷,mamicode.com
首页 > 编程语言 > 详细

CSU1580: Outing(强连通+拓扑排序+dp)

时间:2015-04-26 19:48:33      阅读:273      评论:0      收藏:0      [点我收藏+]

标签:图论   tope   dp   

Description

技术分享

Input

技术分享

Output

技术分享

Sample Input

4 4
1 2 3 4

Sample Output

4

HINT

Source

#include<stdio.h>
#include<vector>
#include<string.h>
using namespace std;
const int N = 1005;
 
int dfn[N],low[N],Stack[N],flag[N],vist[N],num[N],top,deep,tn;
vector<int>mapt1[N],mapt2[N];
 
void init(int n)
{
    for(int i=1;i<=n;i++)
    {
        mapt1[i].clear();
        mapt2[i].clear();
        dfn[i]=0;
        num[i]=0;
        vist[i]=0;
    }
    tn=top=deep=0;
}
int tt;
void tarjan(int u)
{
    vist[u]=tt;
    deep++;
    dfn[u]=low[u]=deep;
    Stack[++top]=u;
 
    int len=mapt1[u].size();
    for(int i=0;i<len;i++)
    {
        int v=mapt1[u][i];
 
        if(vist[v]==0)
        {
            tarjan(v);
            if(low[u]>low[v])
                low[u]=low[v];
        }
        else if(vist[v]==tt&&low[u]>dfn[v])//注意vist[v]==tt
            low[u]=dfn[v];
    }
    if(low[u]==dfn[u])
    {
        tn++;
        while(u!=Stack[top])
        {
            flag[Stack[top]]=tn; num[tn]++;top--; //printf("%d ",Stack[top]);
        }
        flag[Stack[top]]=tn; num[tn]++; top--;
 
    }
}
int in[N],have[N][N];
void rebuilMap(int n)//用强连通缩点,重新反向建图
{
    tt=0;
    for(int i=1;i<=n;i++)
        if(vist[i]==0)
        {
            tt++;
            tarjan(i);
        }
 
    memset(in,0,sizeof(in));
    memset(have,0,sizeof(have));
//缩点后的图无 有向环
    for(int i=1;i<=n;i++)
    {
        int u=flag[i];
        for(int j=0;j<mapt1[i].size();j++)
        {
            int v=flag[mapt1[i][j]];
            if(u==v||have[v][u])
                continue;
            in[u]++; have[v][u]=1;
            mapt2[v].push_back(u);//反向建图,只有v里的人去旅游,u里的人才会去
        }
    }
}
int k;
int tope()
{
    int dp[N],a[N],m=0;
    memset(dp,0,sizeof(dp));
    dp[0]=1;
    for(int i=1;i<=tn;i++)
    if(in[i]==0&&num[i]<=k)//入度为0,且点内的人数小于等于车的坐位数
    {
        a[m++]=i;
        for(int j=k;j>=num[i];j--)
        if(dp[j-num[i]]==1)
            dp[j]=1;
    }
    while(m--)
    {
        int u=a[m];
        for(int i=0;i<mapt2[u].size();i++)
        {
            int v=mapt2[u][i];
            in[v]--;
            if(in[v]==0&&num[v]<=k)
            {
                a[m++]=v;
                for(int j=k;j>=num[v];j--)
                if(dp[j-num[v]]==1)
                    dp[j]=1;
            }
        }
    }
    for(int i=k;i>=0;i--)
        if(dp[i])
        return i;
    return 0;
}
int main()
{
    int n;
    scanf("%d%d",&n,&k);
    {
        init(n);
        for(int i=1;i<=n;i++)
        {
            int j;
            scanf("%d",&j);
            mapt1[i].push_back(j);
        }
        rebuilMap(n);
        printf("%d\n",tope());
    }
    return 0;
}
/*
12 3
2 3 4 5 6 7 4 7 8 8 12 12
 
2
*/
 
/**************************************************************
    Problem: 1580
    User: aking2015
    Language: C++
    Result: Accepted
    Time:8 ms
    Memory:5064 kb
****************************************************************/


CSU1580: Outing(强连通+拓扑排序+dp)

标签:图论   tope   dp   

原文地址:http://blog.csdn.net/u010372095/article/details/45290793

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!