生活随笔
收集整理的這篇文章主要介紹了
Deleting Edges 思维 最短路 删边
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
- 題意 :給一有向圖,刪去圖中某些邊(可以不刪),使剩下的邊構成一顆樹,且0號點到每個點的距離依然為原圖中0號點到每個點的最短距離。求刪邊的方案數,即新圖所有可能性的方案數。
- 思路 :先用dijkstra跑一遍0號點到所有點的最短路,考慮新圖中的每一個點,能讓它成立的方案數是其它最短路的點到它的路徑滿足是它的最短路徑的個數。最后,由于是求總方案數,所以是每個點的方案數相乘。
- 注意這道題是用g中的距離為0表示無法到達,而不是0x3f,所以在初始化和輸入的時候都完全不同!要判斷是否有邊
#include <iostream>
#include <cstring>
#include <queue>using namespace std
;typedef long long ll
;
typedef pair
<int, int> pii
;const int N
= 60;
const ll mod
= 1e9 + 7;int n
;
int g
[N
][N
];
int dist
[N
];
bool st
[N
];
ll cnt
[N
];void dijkstra()
{dist
[0] = 0;priority_queue
<pii
, vector
<pii
>, greater
<pii
>> heap
;heap
.push({0, 0});while (heap
.size()){auto t
= heap
.top();heap
.pop();int ver
= t
.second
, distance
= t
.first
;if (st
[ver
]) continue;st
[ver
] = true;for (int i
= 0; i
< n
; i
++ )if (g
[ver
][i
]) {if (dist
[i
] > dist
[ver
] + g
[ver
][i
]){dist
[i
] = dist
[ver
] + g
[ver
][i
];heap
.push({dist
[i
], i
});}}}
}int main()
{ios
::sync_with_stdio(false); cin
.tie(0); cout
.tie(0);while (cin
>> n
){memset(dist
, 0x3f, sizeof dist
);memset(cnt
, 0, sizeof cnt
);
memset(st
, 0, sizeof st
);for (int i
= 0; i
< n
; i
++ ){string line
;cin
>> line
;for (int j
= 0; j
< n
; j
++ )g
[i
][j
] = line
[j
] - '0';}dijkstra();for (int i
= 0; i
< n
; i
++ )for (int j
= 0; j
< n
; j
++ )if (g
[j
][i
] && dist
[i
] == dist
[j
] + g
[j
][i
]) cnt
[i
] = (cnt
[i
] + 1) % mod
;ll ans
= 1;for (int i
= 1; i
< n
; i
++ ) ans
= ans
* cnt
[i
] % mod
; cout
<< ans
<< endl
;}return 0;
}
總結
以上是生活随笔為你收集整理的Deleting Edges 思维 最短路 删边的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。