本题最关键的地方在于,对于一个单源的最短路径来说,如果最短路树上的边没有改变的话,那么最短路肯定是不会变的,
所以只要枚举删掉最短路树上的边。这样的时间复杂度就能过了。
瞎搞真删边,结果T了。。。
#include<bits/stdc++.h> using namespace std; const int maxn = 102, maxm = 2002; int head[maxn], to[maxm], nxt[maxm],wei[maxm],ecnt; int delta[maxm]; void addEdge(int u,int v,int w) { to[ecnt] = v; nxt[ecnt] = head[u]; wei[ecnt] = w; head[u] = ecnt++; } typedef pair<int,int> Node; #define fi first #define se second int d[maxn],pa[maxn]; typedef long long ll; void dijkstra(int n,int s,int L,bool flag,int e1,int e2)// e1 e2 边应该忽略 { priority_queue<Node,vector<Node>,greater<Node> > q; fill(d,d+n,L); d[s] = 0; q.push(Node(0,s)); pa[s] = -1; while(q.size()){ Node x = q.top(); q.pop(); int u = x.se; if(x.fi != d[u]) continue; for(int i = head[u]; ~i; i = nxt[i])if(i!=e1 && i!=e2) { int v = to[i]; if(d[v] > d[u]+wei[i]){ d[v] = d[u]+wei[i]; if(flag) pa[v] = i; // 入边编号 q.push(Node(d[v],v)); } } } } ll cal(int n) { ll ret = 0; for(int i = 0; i < n; i++){ ret += d[i]; } return ret; } void init() { memset(head,-1,sizeof(head)); ecnt = 0; memset(delta,0,sizeof(delta)); } int main() { //freopen("in.txt","r",stdin); int n,m,L; while(~scanf("%d%d%d",&n,&m,&L)){ init(); while(m--){ int u,v,w; scanf("%d%d%d",&u,&v,&w); addEdge(--u,--v,w); addEdge(v,u,w); } ll ans1 = 0; vector<int> edges; for(int u = 0; u < n; u++){ dijkstra(n,u,L,true,-1,-1); ll t = cal(n); ans1 += t; for(int i = 0; i < n; i++){ if(~pa[i]){ dijkstra(n,u,L,false,pa[i],pa[i]^1); int eid = pa[i]&(~1); if(!delta[eid]) edges.push_back(eid); delta[eid] += cal(n)-t; } } } int MaxDelta = 0; for(int i = 0; i < (int)edges.size(); i++){ MaxDelta = max(MaxDelta,delta[edges[i]]); } printf("%lld %lld\n",ans1,ans1+MaxDelta); } return 0; }
时间: 2024-10-08 15:03:15