Codeforces Round #302 (Div. 2) D

题目链接:

http://codeforces.com/contest/544/problem/D

题意:

有n个城镇,m条边权为1的双向边
让你破坏最多的道路,使得从s1到t1,从s2到t2的距离分别不超过l1和l2

题解:

跑一发最短路,然后最后留下的图肯定是出了s1-t1,s2-t2这两条路之外,其他路都被删除了
那么我们枚举重叠的道路就好了【可能反向】

代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 #define MS(a) memset(a,0,sizeof(a))
 5 #define MP make_pair
 6 #define PB push_back
 7 const int INF = 0x3f3f3f3f;
 8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
 9 inline ll read(){
10     ll x=0,f=1;char ch=getchar();
11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
13     return x*f;
14 }
15 //////////////////////////////////////////////////////////////////////////
16 const int maxn = 3e3+10;
17 
18 int inq[maxn],d[maxn][maxn];
19 vector<int> E[maxn];
20 
21 int main(){
22     int n=read(),m=read();
23     for(int i=0; i<m; i++){
24         int u=read(),v=read();
25         E[u].push_back(v);
26         E[v].push_back(u);
27     }
28 
29     int s1,t1,l1,s2,t2,l2;
30     scanf("%d%d%d%d%d%d",&s1,&t1,&l1,&s2,&t2,&l2);
31 
32     for(int i=1; i<=n; i++){
33         MS(inq);
34         for(int j=0; j<=n; j++) d[i][j] = INF;
35         queue<int> q;
36         q.push(i),inq[i]=1,d[i][i]=0;
37         while(!q.empty()){
38             int now = q.front();
39             q.pop(),inq[now] = 0;
40             for(int k=0; k<(int)E[now].size(); k++){
41                 int v = E[now][k];
42                 if(d[i][v] > d[i][now]+1){
43                     d[i][v] = d[i][now]+1;
44                     if(inq[v]) continue;
45                     inq[v] = 1;
46                     q.push(v);
47                 }
48             }
49         }
50     }
51 
52     if(d[s1][t1]>l1 || d[s2][t2]>l2){
53         cout << -1 << endl;
54         return 0;
55     }
56 
57     int ans = d[s1][t1]+d[s2][t2];
58     for(int i=1; i<=n; i++)
59         for(int j=1; j<=n; j++){
60             if(d[s1][i]+d[i][j]+d[j][t1]<=l1 && d[s2][i]+d[i][j]+d[j][t2]<=l2)
61                 ans = min(ans,d[s1][i]+d[i][j]+d[j][t1]+d[s2][i]+d[j][t2]);
62             if(d[s1][i]+d[i][j]+d[j][t1]<=l1 && d[t2][i]+d[i][j]+d[j][s2]<=l2) // 反向的时候
63                 ans = min(ans,d[s1][i]+d[i][j]+d[j][t1]+d[t2][i]+d[j][s2]);
64         }
65 
66     cout << m-ans << endl;
67 
68     return 0;
69 }
70 /*
71 10 11
72 1 3
73 2 3
74 3 4
75 4 5
76 4 6
77 3 7
78 3 8
79 4 9
80 4 10
81 7 9
82 8 10
83 1 5 3
84 6 2 3
85 */
原文地址:https://www.cnblogs.com/yxg123123/p/6827640.html