#include <iostream>
#include<cstdio>
#include<algorithm>
#include<map>
#include<vector>
#include<cstring>
#include<queue>
using namespace std;
typedef pair<int,int> P;
const int INF =10000000;
int n,m,d[2100],mp[2100][2100],num,nmp[2100][2100];
struct edge
{
int to,cost;
edge(){}
edge(int to,int cost):to(to),cost(cost){}
};
struct nedge
{
int to,cap,rev;
};
vector<edge> g[2100];
vector<int> ng[2100];
vector<nedge> gg[2100];
bool used[2100];
void init(int n)
{
for(int i=0;i<n;i++)
{
g[i].clear();
ng[i].clear();
gg[i].clear();
}
memset(mp,0,sizeof(mp));
memset(nmp,0,sizeof(nmp));
}
void add_edge(int u,int v,int cost)
{
edge e;
e.to=v;e.cost=cost;
g[u].push_back(e);
e.to=u;
g[v].push_back(e);
}
void dijistra(int s)
{
priority_queue<P,vector<P>,greater<P> > que;
fill(d,d+n+1,INF);
d[s]=0;
que.push(P(0,s));
while(!que.empty())
{
P p=que.top();que.pop();
int v=p.second;
if(d[v]<p.first) continue;
for(int i=0;i<g[v].size();i++)
{
edge e=g[v][i];
if(d[e.to]>d[v]+e.cost)
{
d[e.to]=d[v]+e.cost;
que.push(P(d[e.to],e.to));
ng[e.to].clear();
ng[e.to].push_back(v);
}
else if(d[e.to]==d[v]+e.cost)
{
que.push(P(d[e.to],e.to));
ng[e.to].push_back(v);
}
}
}
}
void dfs(int u)
{
used[u]=true;
for(int i=0;i<ng[u].size();i++)
{
int v=ng[u][i];
mp[u-1][v-1]=1;
mp[v-1][u-1]=1;
nmp[u][v]++;
if(used[v])
continue;
dfs(v);
}
}
void add_nedge(int from,int to,int cap)
{
gg[from].push_back((nedge){to,cap,gg[to].size()});
gg[to].push_back((nedge){from,0,gg[from].size()-1});
}
void build()
{
for(int i=1;i<=num;i++)
{
for(int j=1;j<=num;j++)
{
if(i!=j&&nmp[i][j])
{
add_nedge(i,j,nmp[i][j]);
}
}
}
}
int _dfs(int v,int t,int f)
{
if(v==t)return f;
used[v]=true;
for(int i=0;i<gg[v].size();i++)
{
nedge &e=gg[v][i];
if(!used[e.to]&&e.cap>0)
{
int d=_dfs(e.to,t,min(f,e.cap));
if(d>0)
{
e.cap-=d;
gg[e.to][e.rev].cap+=d;
return d;
}
}
}
return 0;
}
int max_flow()
{
build();
int flow=0;
while(1)
{
memset(used,0,sizeof(used));
int f=_dfs(num,1,INF);
if(f==0) return flow;
flow+=f;
}
}
void dijistra0(int s)
{
priority_queue<P,vector<P>,greater<P> > que;
fill(d,d+n+1,INF);
d[s]=0;
que.push(P(0,s));
while(!que.empty())
{
P p=que.top();que.pop();
int v=p.second;
if(d[v]<p.first) continue;
for(int i=0;i<num;i++)
{
if(v==i||mp[v][i]==0)
continue;
if(d[i]>d[v]+mp[v][i])
{
d[i]=d[v]+mp[v][i];
que.push(P(d[i],i));
}
}
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
init(n+10);num=n;
int u,v,cost;
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&u,&v,&cost);
add_edge(u,v,cost);
}
memset(used,0,sizeof(used));
dijistra(1);
if(d[n]>=INF)
{
printf("0 0\n");continue;
}
dfs(n);
printf("%d ",max_flow());
dijistra0(0);
if(d[num-1]>=INF)
d[num-1]=m;
printf("%d\n",m-d[num-1]);
}
return 0;
}
此题主要就是堆模板,很烦
另外反向建边求最短路的图时,忘记了去除访问已经访问过的点,导致点与点之间的连线数量统计出现了问题,最终最大流统计出现了问题,wa了好多次
此题首先是求最短路,求解时记录前缀节点,最后从n点dfs找到所有最短路路径,形成路径图,然后建边求最大流即可得第一问
之后把权值赋值为1,求最短路即经过隧道最少的最短路。