思路:
- 最短路找出允许走的路,然后跑一遍网络流找出从源点到汇点有多少流量。
- Dijkstra,Dinic(Edmonds-Karp会TLE)。
- (第一道网络流,后续会写总结。)
最短路提取://to do
代码:
- Dijkstra+Edmonds-Karp:TLE
#include <iostream>
#include <queue>
#include <cstring>
#include <algorithm>
#include <cstdio>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1005;
int T;
int N,M;
int U,V;
int C[maxn][maxn];
int F[maxn];
int ANS;
int dis[maxn];
struct EDGE{
int to;
int w;
int fo;
}E[maxn * 100] ; int cnt;
int tail[maxn];
void ADDEDGE(int u,int v,int w){
++cnt;
E[cnt].to = v;
E[cnt].w = w;
E[cnt].fo = tail[u];
tail[u] = cnt;
}
struct NODE{
int id;
int dis;
NODE(int id,int dis) : id(id) , dis(dis) {} ;
friend bool operator > (NODE a,NODE b){
return a.dis > b.dis;
}
};
priority_queue<NODE , vector<NODE> , greater<NODE> > Q;
void INIT(){
memset(tail,-1,sizeof(tail));
memset(dis , INF , sizeof(dis));
cnt = 0;
ANS = 0;
return ;
}
void IJK(){
Q.push(NODE(U,0));dis[U] = 0;
while(Q.size()){
NODE cur = Q.top() ; Q.pop();
if(dis[cur.id] < cur.dis)
continue;
for(int i=tail[cur.id] ; ~i ; i=E[i].fo){
int v = E[i].to;
if(dis[v] > dis[cur.id] + E[i].w){
dis[v] = dis[cur.id] + E[i].w;
Q.push(NODE(v,dis[v]));
}
}
}
memset(C,0,sizeof(C));
for(int u=1;u<=N;u++){
for(int i=tail[u] ; ~i ; i=E[i].fo){
if(dis[E[i].to] == dis[u] + E[i].w)
C[u][E[i].to] += 1;
}
}
return ;
}
queue<int> q;
int pre[maxn];
int BFS(){
memset(F,0,sizeof(F));
memset(pre,0,sizeof(pre));
while(q.size())
q.pop();
q.push(U);F[U] = INF;
while(q.size()){
int cur = q.front();q.pop();
if(cur == V)
break;
for(int i=tail[cur] ; ~i ; i=E[i].fo){
int v = E[i].to;
if(C[cur][v] > 0 && !pre[v]){
F[v] = min(F[cur] , C[cur][v]);
pre[v] = cur;
q.push(v);
}
}
}
if(!pre[V])
return 0;
else
return F[V];
}
void Edmonds_Karp(){
int increasement;
while(increasement = BFS()){
int i = V;
while(pre[i]){
C[pre[i]][i] -= increasement;
C[i][pre[i]] += increasement;
i = pre[i];
}
ANS += increasement;
}
return ;
}
int main(){
scanf("%d",&T);
while(T--){
INIT();
scanf("%d%d",&N,&M);
for(int i=1;i<=M;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
if(u == v)
continue;
ADDEDGE(u,v,w);
}
scanf("%d%d",&U,&V);
IJK();
Edmonds_Karp();
printf("%d\n",ANS);
}
return 0;
}
- Dijkstra+Dinic:202ms 6568kB
#include <iostream>
#include <queue>
#include <cstring>
#include <algorithm>
#include <cstdio>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1005;
int T;
int N,M;
int U,V;
int C[maxn][maxn];
int F[maxn];
int ANS;
int dis[maxn];
struct EDGE{
int to;
int w;
int fo;
}E[maxn * 100] ; int cnt;
int tail[maxn];
void ADDEDGE(int u,int v,int w){
++cnt;
E[cnt].to = v;
E[cnt].w = w;
E[cnt].fo = tail[u];
tail[u] = cnt;
}
struct NODE{
int id;
int dis;
NODE(int id,int dis) : id(id) , dis(dis) {} ;
friend bool operator > (NODE a,NODE b){
return a.dis > b.dis;
}
};
priority_queue<NODE , vector<NODE> , greater<NODE> > Q;
void INIT(){
memset(tail,-1,sizeof(tail));
cnt = 0;
ANS = 0;
return ;
}
void IJK(){
memset(dis , INF , sizeof(dis));
Q.push(NODE(U,0));dis[U] = 0;
while(Q.size()){
NODE cur = Q.top() ; Q.pop();
if(dis[cur.id] < cur.dis)
continue;
for(int i=tail[cur.id] ; ~i ; i=E[i].fo){
int v = E[i].to;
if(dis[v] > dis[cur.id] + E[i].w){
dis[v] = dis[cur.id] + E[i].w;
Q.push(NODE(v,dis[v]));
}
}
}
memset(C,0,sizeof(C));
for(int u=1;u<=N;u++){
for(int i=tail[u] ; ~i ; i=E[i].fo){
if(dis[E[i].to] == dis[u] + E[i].w)
C[u][E[i].to] += 1;
}
}
return ;
}
int deep[maxn];
queue<int> q;
bool BFS(){
memset(deep,-1,sizeof(deep));
q.push(U);deep[U]=0;
while(q.size()){
int cur = q.front() ; q.pop() ;
for(int i=1;i<=N;i++){
if(C[cur][i] > 0 && !~deep[i]){
q.push(i);
deep[i] = deep[cur] + 1;
}
}
}
if(~deep[V])
return true;
return false;
}
int DFS(int u,int maxflow){
if(u == V)
return maxflow;
for(int i=1;i<=N;i++){
if(C[u][i] > 0 && deep[i] == deep[u] + 1){
int result = DFS(i , min(maxflow , C[u][i]));
if(result){
C[u][i] -= result;
C[i][u] += result;
return result;
}
}
}
return 0;
}
void DINIC(){
while(BFS()){
while(true){
int aug = DFS(U,INF);
if(!aug) break;
ANS += aug;
}
}
return ;
}
int main(){
scanf("%d",&T);
while(T--){
INIT();
scanf("%d%d",&N,&M);
for(int i=1;i<=M;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
if(u == v)
continue;
ADDEDGE(u,v,w);
}
scanf("%d%d",&U,&V);
IJK();
DINIC();
printf("%d\n",ANS);
}
return 0;
}