题意:
n给顶点,最多1e6条无向边(为什么是1e6,因为wa了一发又一发后试出来的 ),问从1到n的不含重复边的短路有多少条。
思路:
先跑dijkstra跑出最短路,然后挑选出满足最短路径上的边建边,跑最大流即可。
注意:TLE可能是因为边数组开小了,别问我为什么知道 还有n=1的时候答案为0
AC code:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1500 + 100;
const int maxm = 1000050;
const int INF = 0x3f3f3f3f;
struct Dij{
struct Edge{
int to,next;
int w;
}edge[maxm << 1];
int n,m,tot;
int head[maxn];
bool vis[maxn];
void init(int N){
tot = 0;
this->n = N;
for(int i = 0; i <= N; ++i) head[i] = -1;
}
struct node{
int id;
int dis;
node(){};
node(int iid,int dd):id(iid),dis(dd){};
bool operator < (const node &d) const{
return dis > d.dis;
}
}d[maxn];
inline void addedge(int u,int v,int w){
edge[tot] = (Edge){v,head[u],w}, head[u] = tot++;
}
void dijkstra(int s,int t){
for(int i = 0; i <= n; ++i){
d[i].dis = INF, d[i].id = i, vis[i] = 0;
}
priority_queue<node>q;
d[s].dis = 0;
q.push(d[s]);
while(!q.empty()){
int u = q.top().id; q.pop();
if(vis[u]) continue ;
vis[u] = 1;
for(int i = head[u]; ~i; i = edge[i].next){
int v = edge[i].to;
//if(vis[v]) continue ;
if(d[v].dis > d[u].dis + edge[i].w){
d[v].dis = d[u].dis + edge[i].w;
q.push(d[v]);
}
}
}
return ;
}
}D;
#define captype int
struct SAP{
struct Edge{
int from,to,next;
captype cap;
}edge[maxm];
int tot,head[maxn];
int dis[maxn],cur[maxn],pre[maxn],gap[maxn];
void init(int n){
tot = 0;
//memset(head,-1,sizeof(head));
for(int i = 0; i <= n; ++i) head[i] = -1;
}
inline void addedge(int u,int v,captype c,captype rc = 0){
edge[tot] = (Edge){u,v,head[u],c}, head[u] = tot++;
edge[tot] = (Edge){v,u,head[v],rc}, head[v] = tot++;
}
captype max_flow(int s,int t,int n){ //包括源点和汇点在内的总点数
for(int i = 0; i < maxn; ++i){
gap[i] = dis[i] = 0;
cur[i] = head[i];
}
pre[s] = -1, gap[s] = n;
captype ans = 0;
int u = s;
while(dis[s] < n){
if(u == t){
captype minn = INF;
int v;
for(int i = pre[u]; ~i; i = pre[edge[i^1].to]){
if(minn > edge[i].cap){
minn = edge[i].cap, v = i;
}
}
for(int i = pre[u]; ~i; i = pre[edge[i^1].to]){
edge[i].cap -= minn;
edge[i^1].cap += minn;
}
ans += minn;
u = edge[v^1].to;
continue ;
}
bool ok = 0;
int v;
for(int i = cur[u]; ~i; i = edge[i].next){
v = edge[i].to;
if(edge[i].cap > 0 && dis[u] == dis[v] + 1){
ok = 1, cur[u] = pre[v] = i;
break ;
}
}
if(ok){
u = v; continue ;
}
int mind = n;
for(int i = head[u]; ~i; i = edge[i].next){
if(edge[i].cap > 0 && mind > dis[edge[i].to]){
mind = dis[edge[i].to];
cur[u] = i;
}
}
--gap[dis[u]];
if(!gap[dis[u]]) return ans;
dis[u] = mind + 1;
++gap[dis[u]];
if(u != s) u = edge[pre[u]^1].to;
}
return ans;
}
}F;
int a[1000050],b[1000050],c[1000050];
bool vis[1550];
int main(){
int n,T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
D.init(n);
int m = 0;
while(1){
scanf("%d%d%d",&a[m],&b[m],&c[m]);
if(a[m] ==0 && b[m] == 0 && c[m] == 0) break ;
D.addedge(a[m],b[m],c[m]);
D.addedge(b[m],a[m],c[m]);
++m;
}
D.dijkstra(1,n);
if(n == 1 || D.d[n].dis == INF){
puts("0");
continue ;
}
F.init(n);
int u,v;
int s = 0, t = n + 1;
F.addedge(s,1,INF);
F.addedge(n,t,INF);
for(int i = 0; i <= n; ++i) vis[i] = 0;
for(int i = 0; i < m; ++i){
u = a[i], v = b[i];
if(D.d[u].dis > D.d[v].dis) swap(u,v);
if(D.d[v].dis - D.d[u].dis == c[i]){
F.addedge(u,v,1);
vis[u] = vis[v] = 1;
}
}
int cnt = 2;
for(int i = 1; i <= n; ++i) if(vis[i]) ++cnt;
printf("%d\n",F.max_flow(s,t,cnt));
}
return 0;
}