HLG 1540 摧毁车站【dijkstra+dfs】

题意:Colugu市有n个车站和m条路。每条路直接连接两个车站,所有的路都是单向的。为了维护空气质量,政府停用了所有军队车辆。所以军队必须乘坐巴士去机场。

        两个车站之   间可能不只一条路。如果一个车站被摧毁,那么所有通向那个车站的道路都没用了。Gabiluso需要去做的是摧毁一些车站使得军队不能在k分钟内

        赶到机场。一辆巴士通过一条路只需要一分钟。从1到n给所有车站编号。编号为1的车站在军营里,编号为n的车站在机场里。军队总是从编号为1的车站出发

        由于有重兵把守,所以编号为1和n的车站不能被摧毁。当然那里没有一条路直接从1号车站连接到n号车站,请帮助Gabiluso计算他需要摧毁车站的最小数量,他

        必须完成任务。

分析: 要使得1到n的最短距离小于K,删除的点只能是从1到n最短路径上的点,可以递归枚举最短路上去除的点的所有情况找到最优解。

#include<stdio.h>
#include<string.h>
#define clr(x)memset(x,0,sizeof(x))
#define maxn 55
#define INF 0x1f1f1f1f
int g[maxn][maxn];
int d[maxn];
int v[maxn];
int pre[maxn];
int cut[maxn];
int n,K,mcut;
void dijkstra(int *s,int &top)
{
    clr(v);
    int i,u;
    memset(d,INF,sizeof(d));
    d[1]=0;
    while(1)
    {
        u=-1;
        for(i=1;i<=n;i++)
            if(!cut[i]&&v[i]==0&&(d[i]<d[u]||u==-1))
                u=i;
        if(u==-1||d[u]==INF)
            break;
        v[u]=1;
        for(i=1;i<=n;i++)
            if(!cut[i]&&v[i]==0&&g[u][i])
                if(d[u]+1<d[i])
                {
                    d[i]=d[u]+1;
                    pre[i]=u;
                }
        if(v[n])
            break;
    }
    if(d[n]<=K)
    {
        top=0;
        i=pre[n];
        while(i!=1)
        {
            s[top++]=i;
            i=pre[i];
        }
    }
}
void dfs(int ncut)
{
    int i,s[maxn],top;
    dijkstra(s,top);
    if(d[n]>K)
    {
        if(ncut<mcut)
            mcut=ncut;
        return;
    }
    if(mcut<=ncut+1)
        return;
    for(i=0;i<top;i++)
    {
        cut[s[i]]=1;
        dfs(ncut+1);
        cut[s[i]]=0;
    }
}
int main()
{
    int a,b,m;
    while(scanf("%d%d%d",&n,&m,&K),n||m||K)
    {
        clr(g);
        clr(cut);
        mcut=INF;
        while(m--)
        {
            scanf("%d%d",&a,&b);
            g[a][b]=1;
        }
        dfs(0);
        printf("%d\n",mcut);
    }
    return 0;
}

 

posted @ 2012-08-19 21:44  'wind  阅读(300)  评论(0编辑  收藏  举报