CF543B

题目连接:CodeForces - 543B

Let's solve easiest task. We have only one pair of vertices, and we need to calculate smallest amout of edges, such that there is a path from first of vertex to the second. It's clear, that the answer for that problem equals to shortest distance from first vertex to the second.

Let's come back to initial task. Let's d[i][j] — shortest distance between i and j. You can calculate such matrix using bfs from each vertex.

Now we need to handle two cases:

  1. Paths doesn't intersects. In such way we can update the answer with the following value: m - d[s0][t0] - d[s1][t1] (just in case wheh conditions on the paths lengths fullfills).
  2. Otherwise paths are intersecting, and the correct answer looks like a letter 'H'. More formally, at the start two paths will consists wiht different edges, after that paths will consists with same edges, and will finish with different edges. Let's iterate over pairs (i, j) — the start and the finish vertices of the same part of paths. Then we can update answer with the following value:m - d[s0][i] - d[i][j] - d[j][t0] - d[s1][i] - d[j][t1] (just in case wheh conditions on the paths lengths fullfills).

Please note, that we need to swap vertices s0 and t0, and recheck the second case, because in some situations it's better to connect vertex t0 with vertex i and s0 with vertex j. Solutions, which didn't handle that case failed system test on testcase 11.

The jury solution: 11035716

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=3010;
 4 
 5 struct edge
 6 {
 7     int v,nex;
 8 }e[maxn<<1];
 9 int head[maxn];
10 int cnt;
11 void add(int u,int v)
12 {
13     e[cnt].v=v;
14     e[cnt].nex=head[u];
15     head[u]=cnt++;
16 }
17 
18 int d[maxn][maxn];
19 int n,m,u,v;
20 int s1,e1,l1,s2,e2,l2;
21 void bfs(int x)
22 {
23     d[x][x]=0;
24     queue<int> q;
25     q.push(x);
26     while(!q.empty())
27     {
28         int u=q.front();
29         q.pop();
30         for(int i=head[u];i!=-1;i=e[i].nex)
31         {
32             int v=e[i].v;
33             if(d[x][v]==-1)
34             {
35                 d[x][v]=d[x][u]+1;
36                 q.push(v);
37             }
38         }
39     }
40     return ;
41 }
42 int main()
43 {
44     scanf("%d%d",&n,&m);
45     memset(d,-1,sizeof(d));
46     memset(head,-1,sizeof(head));
47     cnt=0;
48     for(int i=0;i<m;i++)
49     {
50       scanf("%d%d",&u,&v);
51       add(u,v);
52       add(v,u);
53     }
54     scanf("%d%d%d%d%d%d",&s1,&e1,&l1,&s2,&e2,&l2);
55     for(int i=1;i<=n;i++)
56     bfs(i);
57     int ans=m+1;
58     for(int r=0;r<2;r++)
59     {
60         swap(s2,e2);
61     for(int i=1;i<=n;i++)
62         for(int j=1;j<=n;j++)
63         {
64             int v[]={d[s1][i]+d[i][j]+d[j][e1],d[s2][i]+d[i][j]+d[j][e2]};
65             if(v[0]<=l1&&v[1]<=l2)
66             {
67                 ans=min(ans,v[0]+v[1]-d[i][j]);
68             }
69         }
70     }
71     if(d[s1][e1]<=l1&&d[s2][e2]<=l2)
72         ans=min(ans,d[s1][e1]+d[s2][e2]);
73     if(ans>m) ans=-1;
74     else ans=m-ans;
75     printf("%d\n",ans);
76 }

 

转载于:https://www.cnblogs.com/yijiull/p/6809668.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值