二分图--匈牙利算法匹配
P2319 [HNOI2006] 超级英雄
P1894[USACO4.2] 完美的牛栏The Perfect Stall
P2071 座位安排
分层图
P4822 [BJWC2012] 冻结
P4568[JLOI2011] 飞行路线
P2939 [USACO09FEB] Revamping Trails G
最短路
P2149[SDOI2009] Elaxia的路线
Elaxia 和 w** 的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们必须合理地安排两个人在一起的时间。
Elaxia 和 w** 每天都要奔波于宿舍和实验室之间,他们 希望在节约时间的前提下,一起走的时间尽可能的长。
现在已知的是 Elaxia 和 w** 所在的宿舍和实验室的编号以及学校的地图:
地图上有n 个路口,m 条路,经过每条路都需要一定的时间
题意:求无向图中,两对点间最短路的最长公共路径的长度
筛出最短路的边
思路:分别求出从s1,t1,s2,t2出发的最短路,筛出s1到t1的最短路的边
之后同样在这些边求出并行走,反向走的最长公共路径
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #define endl '\n'
- #define ios ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
- #define ms(x,y) memset(x,y,sizeof x);
- #define YES cout<<"YES"<<'\n';
- #define NO cout<<"NO"<<'\n';
- #define fr(i,z,n) for(int i = z;i <= n; i++)
- #define fer(i,x) for(int i=e.head[x];i;i=e.next[i])
- #define ufr(i,n,z) for(int i = n;i >= z; i--)
- #define int long long
- typedef long long ll;
- const ll N = 1e6 + 10, inf = 1e18;
- const ll mod = 1e9 + 7;
- using namespace std;
- template<size_t size>
- struct Road {
- int to[size], next[size], head[size], cnt = 1;
- ll w[size];
- void add(int x, int y, ll ww) {
- to[cnt] = y;
- w[cnt] = ww;
- next[cnt] = head[x];
- head[x] = cnt++;
- }
- void clear(int n) {
- for (int i = 0; i <= n; i++) {
- head[i] = 0;
- }
- cnt = 1;
- }
- };
- Road
e; - int dis[4][N];
- bool vis[N];
- int n, m;
- int ok[N], in[N];
- int f[N], g[N]; //记录反向走和并行走两种情况
- void spfa(int u,int k) {
- fr(i, 1, n) {
- dis[k][i] = 0x3f3f3f3f;
- vis[i] = 0;
- }
- vis[u] = 1;
- dis[k][u] = 0;
- queue<int>q;
- q.push(u);
- while (!q.empty()) {
- int x = q.front();
- q.pop();
- vis[x] = 0;
- fer(i, x) {
- int v = e.to[i];
- int w = e.w[i];
- if (dis[k][x] + w < dis[k][v]) {
- dis[k][v] = dis[k][x] + w;
- if (!vis[v]) {
- q.push(v);
- vis[v] = 1;
- }
- }
- }
- }
- }
- void solve() {
- cin >> n >> m;
- int s1, t1, s2, t2;
- cin >> s1 >> t1 >> s2 >> t2;
- fr(i, 1, m) {
- int x, y,w;
- cin >> x >> y >> w;
- e.add(x, y, w);
- e.add(y, x, w);
- }
- spfa(s1, 0); spfa(t1, 1); //最短路
- spfa(s2, 2); spfa(t2, 3);
- fr(u, 1, n) { //选出最短路中的有用边
- fer(i, u) {
- int w = e.w[i];
- int v = e.to[i];
- if ((dis[0][u] + w+dis[1][v])==dis[0][t1]) {
- //s1到u的最短路+u到v的距离+v到t1的最短路==s1到t1的最短路
- ok[i] = 1;
- in[v]++;
- }
- }
- }
- int ans = 0;
- queue<int>q;
- q.push(s1);
- while (!q.empty()) { //拓扑排序
- int u = q.front();
- q.pop();
- ans = max({ g[u], f[u],ans });
- fer(i, u) {
- if (ok[i]) { //有用边
- int v = e.to[i];
- int w = e.w[i];
- in[v]--;
- if (in[v] == 0) {
- q.push(v);
- }
- if ((dis[2][u] + w + dis[3][v]) == dis[2][t2]) { //筛出有用边
- //从s2到u的最短路+u到v的距离+v到t2的最短路=s2到t2的最短路
- //并行走
- g[v] = max(g[v], g[u] + w);
-
- }
- if((dis[3][u] + w + dis[2][v]) == dis[2][t2]) {
- //从t2到u的最短路+u到v的距离+v到s2的最短路=s2到t2的最短路
- //反向走
- f[v] = max(f[v], f[u] + w);
- }
-
- }
- }
- }
- cout << ans << '\n';
- }
-
- signed main()
- {
- ios;
- int t = 1;
- //cin >> t;
- while (t--) {
- solve();
- }
- }