Codevs1021 玛丽卡

  • 题目大意:给定一张无向图,求拆去任意一边后由1至N最短路的最大值。

  • 在程序中:存图时采用邻接表。利用堆优化dijkstra算法多次求最短路,第一次设置flag为true将路径上的点记录于pre[ ]数组中,再利用过程getpath( )求出相关点。在删边时,将边上的两点u,v的数组arrive[ ]值均置为false,求最短路时若某边的两点i,j的arrive[ ]值均为false则跳过,过后恢复。最后对ans与dis[n]求最大值。

  • 程序如下:
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
struct edge
{
    int to,cost;
    edge(int to=0,int cost=0):to(to),cost(cost){}
};
struct node
{
    int id,len;
    node(int id=0,int len=0):id(id),len(len){}
    bool operator <(const node &a) const
    {
        return len>a.len;
    }
};
const int maxn=1005;
const int oo=100000;
int n,m,pre[maxn],ans=0;
vector<edge> g[maxn];
bool arrive[maxn];

void init()
{
    memset(pre,-1,sizeof(pre));
    memset(arrive,1,sizeof(arrive));
    int a,b,v;
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;++i)
    {
        scanf("%d%d%d",&a,&b,&v);
        g[a].push_back(edge(b,v));
        g[b].push_back(edge(a,v));
    }
}

int dis[maxn];
bool vis[maxn];
int dijkstra(bool flag)
{
    int i,j,k;
    priority_queue<node> q;
    memset(vis,0,sizeof(vis));
    for (i=1;i<=n;++i)
      dis[i]=oo;
    dis[1]=0;
    q.push(node(1,0));
    for (i=1;i<=n;++i)
    {
        while (q.size() && vis[q.top().id])
           q.pop();
        if (q.empty())
          break;
        int x=q.top().id;
        q.pop();
        vis[x]=1;
        vector<edge>::iterator it;
        for (it=g[x].begin();it!=g[x].end();++it)
        {
            if ( (arrive[(*it).to] || arrive[x]) && !vis[(*it).to] && dis[(*it).to]>dis[x]+(*it).cost)
            {
                dis[(*it).to]=dis[x]+(*it).cost;
                if (flag)
                {
                    pre[(*it).to]=x;
                }
                q.push(node((*it).to,dis[(*it).to]));
            }
        }
    }
}

int path[maxn],cnt=1;
void getpath()
{
    int p=path[1]=n;
    while (pre[p]!=1)
    {
        p=pre[p];
        path[++cnt]=p;
    }
    path[++cnt]=1;
}

int main()
{
    init();
    dijkstra(true);
    getpath();  
    for (int j=1;j<=cnt-1;++j)
    {
        arrive[path[j]]=false;
        arrive[path[j+1]]=false;
        dijkstra(false);
        if (dis[n]>ans)
          ans=dis[n];
        arrive[path[j]]=true;
        arrive[path[j+1]]=true;
    }
    printf("%d",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值