zoukankan      html  css  js  c++  java
  • 洛谷 P2176(最短路)

    ###题目链接 洛谷 P2176 ###

    题目大意:

    已知农夫从 1 走到 N 点,一定走的是最短路。问你将某条路的长度变为其两倍后,农夫从 1 走到 N 点的路程最大增加多少,输出最大增量。

    分析:

    1、很显然,如果增大某条路长度会使得最短路增加,那么这条路必为原先最短路径上的某条路。

    2、故只需要记录边的 id ,然后依次枚举该条路长度翻倍后的最短路径,然后取与一开始最短路的差值的最大值即可。

    3、记得用 id[] 存储路径编号,然后要分别更改这条路径两个方向的边的值(因为是无向边)。

    4、时间复杂度应该是 N * M * logM ,本题大约为 107 ,1s 应该够了。

    代码如下:

    #define IO freopen("test.in","r",stdin),freopen("test.out","w",stdout)
    #include <set>
    #include <map>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <cmath>
    #include <ctime>
    #include <bitset>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <cstdlib>
    #include <cstring>
    #include <cassert>
    #include <iostream>
    #include <algorithm>
    #include <unordered_map>
    using namespace std;
    #define inf 0x3f3f3f3f
    #define maxn 108
    typedef pair<int,int> P;
    int n,m,cnt;
    int head[maxn],dist[maxn],pre[maxn],id[maxn],a[maxn];
    bool vis[maxn];
    struct Edge
    {
        int to;
        int val;
        int next;
    }edge[10008];
    inline void add(int u,int v,int w)
    {
        edge[++cnt].to=v;
        edge[cnt].val=w;
        edge[cnt].next=head[u];
        head[u]=cnt;
        return;
    }
    int dijkstra()
    {
        for(int i=1;i<=n;i++) dist[i]=inf,vis[i]=false;
        priority_queue<P,vector<P>,greater<P> > q;
        while(!q.empty()) q.pop();
        q.push(make_pair(0,1));
        dist[1]=0;
        while(!q.empty())
        {
            int u=q.top().second,t=q.top().first;
            q.pop();
            if(vis[u]) continue;
            if(u==n) return dist[n];
            vis[u]=true;
            for(int i=head[u];i;i=edge[i].next){
                int v=edge[i].to;
                if(dist[v]>dist[u]+edge[i].val){
                    dist[v]=dist[u]+edge[i].val;
                    pre[v]=u,id[v]=i;
                    q.push(make_pair(dist[v],v));
                }
            }
        }
        return dist[n];
    }
    int main()
    {
        //IO;
        scanf("%d%d",&n,&m);
        int A,B,C;
        while(m--)
        {
            scanf("%d%d%d",&A,&B,&C);
            add(A,B,C),add(B,A,C);
        }
        int s=dijkstra();
        int x=n;
        cnt=0;
        while(id[x]){
            a[++cnt]=id[x];
            x=pre[x];
        }
        int ans=-1;
        for(int i=1;i<=cnt;i++){
            if(a[i]%2==0){
                edge[a[i]-1].val*=2,edge[a[i]].val*=2;
                int res=dijkstra();
                ans=max(ans,res-s);
                edge[a[i]-1].val/=2,edge[a[i]].val/=2;
            }
            else{
                edge[a[i]].val*=2,edge[a[i]+1].val*=2;
                int res=dijkstra();
                ans=max(ans,res-s);
                edge[a[i]].val/=2,edge[a[i]+1].val/=2;
            }
        }
        printf("%d
    ",ans );
    }
  • 相关阅读:
    Context Menu on DataGrid
    DataGrid Column Group (合并表头)
    DataGrid loadData loadFilter
    sharepoint 2010 FieldLookup 的更新方法
    SharePoint 2010 列表查阅项栏的formfield控件对象取值
    sharepoint2010的几个类型字段赋值和取值的方法
    SharePoint 和 Windows Phone 7 开发人员培训资源
    如何提升SharePoint 2010的性能
    sharepoint国内网站一览表(转发)
    sharepoint2010列表的分页实现迅雷样式效果
  • 原文地址:https://www.cnblogs.com/Absofuckinglutely/p/11504487.html
Copyright © 2011-2022 走看看