https://szkopul.edu.pl/problemset/problem/EFdkaacNCEGVDXbpjynafz2n/site/?key=statement
自己想了个方法(常数超大,14倍常数???):每条原图中边看成一个点(无向边先不拆开)建新图后,就是要解决一个问题:给出一些点,现在要在它们两两连边(无向),边权为两个端点点权间较大值,要求优化连边。有做法:每一次要连边了,先将这些点按点权从小到大排序,然后相当于每个点u要和排在它之前的所有点连边权为u点权的边。为了达到这个目标,先将无向图改成有向图。先考虑"从某个点之前的所有点向那个点连边":每一次要连边时,对于每个点新建一个辅助点,辅助点之间按照排好序的顺序每一个点向后一个点连边权为0的边,每个辅助点向其对应原点连边权为点权的边,每个原点向对应辅助点连边权为0的边。”从某个点向之前所有点连边”也可以用类似方法完成。

1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<vector> 5 #include<queue> 6 using namespace std; 7 #define fi first 8 #define se second 9 #define mp make_pair 10 #define pb push_back 11 typedef long long ll; 12 typedef unsigned long long ull; 13 typedef pair<ll,int> pli; 14 typedef pair<int,int> pii; 15 struct E 16 { 17 int to,nxt;ll d; 18 }e[3000100]; 19 int f1[1000100],ne; 20 void me(int x,int y,ll z) 21 { 22 //printf("1t%d %d %d ",x,y,z); 23 e[++ne].to=y;e[ne].nxt=f1[x];f1[x]=ne;e[ne].d=z; 24 } 25 struct EE 26 { 27 int x,y;ll z; 28 }e1[200010]; 29 vector<int> a1[100010]; 30 int t2[200010],t1[200010]; 31 int n,m,n1,S,T; 32 ll d[1000100]; 33 priority_queue<pli,vector<pli>,greater<pli> > q; 34 bool v1[1000100]; 35 //int pre[1000100]; 36 bool c1(int a,int b){return e1[a].z<e1[b].z;} 37 int main() 38 { 39 int i,j,x,y,u,k;pli t;ll z; 40 scanf("%d%d",&n,&m);n1=m; 41 S=++n1;T=++n1; 42 for(i=1;i<=m;++i) 43 { 44 scanf("%d%d%lld",&x,&y,&z); 45 e1[i].x=x;e1[i].y=y;e1[i].z=z; 46 a1[x].pb(i); 47 a1[y].pb(i); 48 if(x==1||y==1) me(S,i,z); 49 if(x==n||y==n) me(i,T,z); 50 } 51 for(i=1;i<=n;++i) 52 if(a1[i].size()>1) 53 { 54 sort(a1[i].begin(),a1[i].end(),c1); 55 for(j=0;j<a1[i].size();++j) 56 { 57 t1[j]=++n1;t2[j]=++n1; 58 z=e1[a1[i][j]].z; 59 me(a1[i][j],t1[j],0); 60 me(t1[j],a1[i][j],z); 61 me(a1[i][j],t2[j],z); 62 me(t2[j],a1[i][j],0); 63 } 64 for(j=1;j<a1[i].size();++j) 65 { 66 me(t1[j-1],t1[j],0); 67 me(t2[j],t2[j-1],0); 68 } 69 } 70 memset(d,0x3f,sizeof(d)); 71 q.push(pli(0,S));d[S]=0; 72 while(!q.empty()) 73 { 74 t=q.top();q.pop(); 75 u=t.se; 76 if(v1[u]) continue; 77 v1[u]=1; 78 for(k=f1[u];k;k=e[k].nxt) 79 if(d[e[k].to]>d[u]+e[k].d) 80 { 81 d[e[k].to]=d[u]+e[k].d; 82 //pre[e[k].to]=u; 83 q.push(pli(d[e[k].to],e[k].to)); 84 } 85 } 86 printf("%lld ",d[T]); 87 //for(int u=T;u;u=pre[u]) printf("2t%d %d ",u,d[u]); 88 return 0; 89 }