Codeforces Round #302 (Div. 1) B Destroying Roads(最短路+枚举)

来源:互联网 发布:白苹果修复数据还在吗 编辑:程序博客网 时间:2024/04/29 15:31

关键词:bfs求单源最短路径、O(n^2)枚举相交路径
题意:在一个有向图中删除尽量多的边使得s1->t1,s2->t2的最短路分别不大于l1和l2
解法:
1.bfs求单源最短路径。遍历所有的顶点,求出所有点源最短路
2.枚举两条道路的相交路径。相交路径仅加一次即可

思路分析:
从删边后的结果出发,s1->t1,s2->t2有一段相交路径,其余部分不相交。要使删边最大,就要使留下的边长和最小。因此
s1->t1,s2->t2均由三条最短路组成。枚举中间的那条最短路两端点维护剩余图的最小边长和。

#include<stdio.h>#include<string.h>#include<algorithm>#include<iostream>#include<vector>#include<queue>#define mem(a,b) memset(a,sizeof(a),b)#define ll long longusing namespace std;const int maxn = 3000+10;int n,m;vector<int> e[maxn];int s[2],t[2],l[2];int ans;int d[maxn][maxn];void bfs(int x){    queue<int> q;    for(int i=1;i<=n;i++) d[x][i]=-1;    q.push(x),d[x][x]=0;    while(!q.empty()){        int u=q.front(); q.pop();        for(int i=0;i<e[u].size();i++){            int v=e[u][i];            if(d[x][v]==-1){                d[x][v]=d[x][u]+1;                q.push(v);            }        }    }}int main(){    //freopen("a.txt","r",stdin);    scanf("%d%d",&n,&m);    for(int i=0;i<m;i++){        int a,b;        scanf("%d%d",&a,&b);        e[a].push_back(b),e[b].push_back(a);    }    for(int i=1;i<=n;i++) bfs(i);    for(int i=0;i<2;i++) scanf("%d%d%d",&s[i],&t[i],&l[i]);    if(d[s[0]][t[0]]>l[0]||d[s[1]][t[1]]>l[1]){        printf("-1\n");        return 0;    }    ans=d[s[0]][t[0]]+d[s[1]][t[1]];    for(int i=1;i<=n;i++){        for(int j=1;j<=n;j++){            int l1=d[s[0]][i]+d[i][j]+d[j][t[0]],l2=d[s[0]][j]+d[j][i]+d[i][t[0]];            int l3=d[s[1]][i]+d[i][j]+d[j][t[1]];            if(l1<=l[0]&&l3<=l[1]) ans=min(ans,l1+d[s[1]][i]+d[j][t[1]]);            if(l2<=l[0]&&l3<=l[1]) ans=min(ans,l2+d[s[1]][i]+d[j][t[1]]);        }    }    printf("%d\n",m-ans);}
0 0
原创粉丝点击