zoukankan      html  css  js  c++  java
  • 2020hdu多校第三场1009(6797)Tokitsukaze and Rescue

    题目地址http://acm.hdu.edu.cn/showproblem.php?pid=6797

    题意:有n个点的完全无向图,也就是有n(n-1)/2条无向边,删除k条边之后使得从一号节点到n号节点的最短路径最长,求出次最短路径的最大值

    输入:第一行一个整数t,表示样例个数

    每个样例第一行两个整数n,k

    接下来n(n-1)/2行,每行三个整数u,v,w,表示u,v之间存在一条权值为w的无向边

    输出:对于每个样例输出一个整数,表示删除k条边之后的最短路径的最大值

    题解:这里面n<=50,k<=min(n-2,5),所以这里直接dfs递归深搜就可以,但比赛的时候没敢尝试,的确非常后悔。先找出一条最短路径,遍历删除路径上的每一条边,然后继续dfs,在删除求出的最短路径上的每一条边,如此直到删除k条边表示一次dfs结束,知道左右可能的情况都遍历之后求出的就是最后的答案

    AC代码

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring> 
    using namespace std;
    const int N=50+2;
    int e[N][N];
    int p[N];
    int dis[N];
    int n,k,sum;
    int pre[6][N];
    struct node{
        int x,s;
    }a,b;
    bool operator>(struct node a,struct node b){
        return a.s>b.s;
    }
    int dij(int x){
        priority_queue<struct node,vector<struct node>,greater<struct node> >q;
        memset(p,0,sizeof(p));
        memset(dis,0,sizeof(dis));
        p[1]=1;
        a.x=1,a.s=0;
        q.push(a);
        while(!q.empty()){
            a=q.top();q.pop();
            p[a.x]=1;
            if(a.x==n) break;
            for(int i=2;i<=n;i++){
                if(p[i]||e[i][a.x]==-1) continue;
                b.x=i,b.s=a.s+e[a.x][i];
                if(dis[i]==0||b.s<dis[i]){
                    q.push(b);
                    dis[i]=b.s;
                    pre[x][i]=a.x;//这里表示删除x条边之后的最短路径中i的前一个结点,
                    //第一次写的时候直接使用的一维数组,结果一直WA,最后才发现原来当你下一次深搜之后pre就会被改变,
                    //当返回上一层的dfs时继续便利pre就不是原先的pre,就会产生错误 
                }
            }
        }
        while(!q.empty()) q.pop();
        return a.s;
    }
    void dfs(int x){
        if(x==k){
            if(sum==-1) sum=dij(x);
            else sum=max(sum,dij(x));
            return ;
        }
        dij(x);//当删除x条边之后进行的最短路搜索 
        int now=n,w;//之前写的是now=pre[x][now]然后一直出错,原来要是这么写的话,那么与n节点相连的边就不会被遍历到了 
        while(pre[x][now]!=-1){
            w=e[now][pre[x][now]];
            e[now][pre[x][now]]=-1;
            e[pre[x][now]][now]=-1;//之前没有这一行与下面有注释的那行,然后一直WA,最后才发现自己是真的马虎 
            dfs(x+1);
            e[now][pre[x][now]]=w;
            e[pre[x][now]][now]=w;//与上面标注的那行同时没有写 
            now=pre[x][now];
        }
    }
    int main(){
        int t;cin>>t;
        while(t--){
            sum=-1;
            memset(pre,-1,sizeof(pre));
            cin>>n>>k;
            int u,v;
            for(int i=1;i<=n*(n-1)/2;i++){
                cin>>u>>v;
                cin>>e[u][v];//使用它邻接矩阵存储图 
                e[v][u]=e[u][v];
            }
            dfs(0);//深搜,0表示当前已经删除0条边 
            cout<<sum<<endl;
        }
        return 0;
    }
    View Code

    写于2020/7/31  14:23


    作者:孙建钊
    出处:http://www.cnblogs.com/sunjianzhao/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    男人应该懂得的
    喝酒礼仪
    Office Web Apps开放测试
    SAP系统概要
    SAP实施成功的关键因素
    SAP企业实施的方法论
    ASAP
    ERP系统的组成部分
    去除word的保护
    实习周小结
  • 原文地址:https://www.cnblogs.com/sunjianzhao/p/13409484.html
Copyright © 2011-2022 走看看