http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1444
无向图直接用广度优先搜索求出两点之间的最小距离,然后剩下的就是要去掉重复边,直接暴力。
因为已经求得最短路了,但是2个道路之间可能有重叠的部分,我们枚举它是i到j,然后分情况讨论一下就ok了,每条都分为头或尾与i相连两种情况!
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
#include <queue>
#pragma warning(disable:4996)
using namespace std;
int n, m;
int s1, t1, l1;
int s2, t2, l2;
vector<int>connect[3005];
int dis[3005][3005];
int vis[3005];
void bfs()
{
int i, k, temp, v, size;
for (i = 1; i <= n; i++)
{
memset(vis, 0, sizeof(vis));
queue<int>q;
q.push(i);
vis[i] = 1;
while (!q.empty())
{
temp = q.front();
q.pop();
size = connect[temp].size();
for (k = 0; k < size; k++)
{
v = connect[temp][k];
if (vis[v])continue;
vis[v] = 1;
dis[i][v] = dis[i][temp] + 1;
q.push(v);
}
}
}
}
int main()
{
int i, j, temp1, temp2;
scanf("%d%d", &n, &m);
sizeof(dis, 0, sizeof(dis));
for (i = 1; i <= m; i++)
{
scanf("%d%d", &temp1, &temp2);
connect[temp1].push_back(temp2);
connect[temp2].push_back(temp1);
}
scanf("%d%d%d", &s1, &t1, &l1);
scanf("%d%d%d", &s2, &t2, &l2);
bfs();
int ans = dis[s1][t1] + dis[s2][t2];
if (dis[s1][t1] > l1 || dis[s2][t2] > l2)
{
printf("-1\n");
}
else
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (dis[s1][i] + dis[i][j] + dis[j][t1] <= l1&&dis[s2][i] + dis[i][j] + dis[j][t2] <= l2)
{
ans = min(ans, dis[s1][i] + dis[i][j] + dis[j][t1] + dis[s2][i] + dis[j][t2]);
}
if (dis[t1][i] + dis[i][j] + dis[j][s1] <= l1&&dis[t2][i] + dis[i][j] + dis[j][s2] <= l2)
{
ans = min(ans, dis[t1][i] + dis[i][j] + dis[j][s1] + dis[t2][i] + dis[j][s2]);
}
if (dis[s1][i] + dis[i][j] + dis[j][t1] <= l1&&dis[t2][i] + dis[i][j] + dis[j][s2] <= l2)
{
ans = min(ans, dis[s1][i] + dis[i][j] + dis[j][t1] + dis[t2][i] + dis[j][s2]);
}
if (dis[t1][i] + dis[i][j] + dis[j][s1] <= l1&&dis[s2][i] + dis[i][j] + dis[j][t2] <= l2)
{
ans = min(ans, dis[t1][i] + dis[i][j] + dis[j][s1] + dis[s2][i] + dis[j][t2]);
}
}
}
printf("%d\n", m - ans);
}
return 0;
}