(spfa记录路径)hdu1595+hdu3986

来源:互联网 发布:centos搭建vpn网速慢 编辑:程序博客网 时间:2024/04/20 20:20

题目大意:

其实这两道题大体意思是相同的,就是给你一个图,给定起点和终点,问你在可以毁坏一条路的情况下,从起点到终点的最短路的最远距离。

解题思路

可以看出如果破坏的路不是最短路中的一条,那么实际上不会改变最远距离(因为都是最短路那么长)。所以我们要得到最大答案那么一定是想办法破坏最短路上的边。所以这里枚举破坏最短路上的边即可。

这两道题不同的地方是是前者没有重边,所以我选择通过记录前驱点来记录路径。而后者有可能有重边,所以只能通过记录边的下标来记录路径。

代码hdu1595:

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<string>#include<vector>#include<stack>#include<bitset>#include<cstdlib>#include<cmath>#include<set>#include<list>#include<deque>#include<map>#include<queue>using namespace std;typedef long long ll;const double PI = acos(-1.0);const double eps = 1e-6;const int INF = 0x3f3f3f3f;const int maxn = 1234;int T,n,m,tot;int ans,once;int vis[maxn];int head[maxn];int dis[maxn];int path[maxn];struct EDGE{    int to;    int w;    int next;}edge[maxn*maxn/2];void init(){    once=1;    tot=0;    memset(head,-1,sizeof(head));    memset(vis,0,sizeof(vis));    memset(path,0,sizeof(path));}void add_edge(int u,int v,int w){    edge[tot].to=v;    edge[tot].w=w;    edge[tot].next=head[u];    head[u]=tot++;}int spfa(){    memset(dis,INF,sizeof(dis));    queue<int>q;    q.push(1);    vis[1]=1;    dis[1]=0;    path[1]=0;    while(!q.empty())    {        int u=q.front();        q.pop();        vis[u]=0;        for(int i=head[u];i!=-1;i=edge[i].next)        {            int v=edge[i].to;            int w=edge[i].w;            if(w+dis[u]<dis[v])            {                if(once)                    path[v]=u;                dis[v]=dis[u]+w;                if(vis[v]==0)                {                    q.push(v);                    vis[v]=1;                }            }        }    }    return dis[n];}void print_path(int k){    if(path[k])        print_path(path[k]);    printf("%d ",k);}int main(){    while(scanf("%d%d",&n,&m)!=EOF)    {        init();        for(int i=0;i<m;i++)        {            int a,b,c;            scanf("%d%d%d",&a,&b,&c);            add_edge(a,b,c);            add_edge(b,a,c);        }        ans=spfa();        once=0;        //枚举删除最短路上的路,求最长结果        int k=n;        while(path[k])        {            int pos1,pos2;            int val;            //删双向边            for(int i=head[k];i!=-1;i=edge[i].next)            {                if(edge[i].to==path[k])                {                    pos1=i;                    val=edge[i].w;                    edge[i].w=INF;                    break;                }            }            for(int i=head[path[k]];i!=-1;i=edge[i].next)            {                if(edge[i].to==k)                {                    pos2=i;                    edge[i].w=INF;                    break;                }            }            ans=max(ans,spfa());            //恢复边            edge[pos1].w=val;            edge[pos2].w=val;            k=path[k];        }        printf("%d\n",ans);    }    return 0;}

代码hdu3986:

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<string>#include<vector>#include<stack>#include<bitset>#include<cstdlib>#include<cmath>#include<set>#include<list>#include<deque>#include<map>#include<queue>using namespace std;typedef long long ll;const double PI = acos(-1.0);const double eps = 1e-6;const int INF = 0x3f3f3f3f;const int maxn = 1234;int T,n,m,tot;int ans,once;int vis[maxn];int vis_edge[maxn*maxn/2];int head[maxn];int dis[maxn];int path[maxn];struct EDGE{    int from;    int to;    int w;    int next;}edge[maxn*maxn/2];void init(){    once=1;    tot=0;    memset(head,-1,sizeof(head));    memset(vis_edge,0,sizeof(vis_edge));    memset(vis,0,sizeof(vis));    memset(path,-1,sizeof(path));}void add_edge(int u,int v,int w){    edge[tot].from=u;    edge[tot].to=v;    edge[tot].w=w;    edge[tot].next=head[u];    head[u]=tot++;}int spfa(){    memset(dis,INF,sizeof(dis));    queue<int>q;    q.push(1);    vis[1]=1;    dis[1]=0;    while(!q.empty())    {        int u=q.front();        q.pop();        vis[u]=0;        for(int i=head[u];i!=-1;i=edge[i].next)        {            if(vis_edge[i]==1)                continue;            int v=edge[i].to;            int w=edge[i].w;            if(w+dis[u]<dis[v])            {                if(once)                    path[v]=i;                dis[v]=dis[u]+w;                if(vis[v]==0)                {                    q.push(v);                    vis[v]=1;                }            }        }    }    return dis[n];}int main(){    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&m);        init();        for(int i=0;i<m;i++)        {            int a,b,c;            scanf("%d%d%d",&a,&b,&c);            add_edge(a,b,c);            add_edge(b,a,c);        }        ans=spfa();        once=0;        int k=n;        while(path[k]!=-1)        {            if(ans>=INF)                break;            vis_edge[path[k]]=vis_edge[path[k]+1]=1;            ans=max(ans,spfa());            vis_edge[path[k]]=vis_edge[path[k]+1]=0;            k=edge[path[k]].from;        }        if(ans>=INF)            printf("-1\n");        else            printf("%d\n",ans);    }    return 0;}
原创粉丝点击