Description
给出一个n个点,m条边的无向图。你可以选择一个点x,把x相连得边边权变为1.求1~n的最短路。
n<=10^5,m<=n*5
Solution
辣鸡出题人,卡我空间。
很多神奇的做法,你可以直接分层,然后一边最短路。
或者两边最短路,然后枚举修改的点。
随便乱搞一下就好啦!!
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define rep(i,a) for(int i=last[a];i;i=next[i])
#define N 300005
#define M 8000005
using namespace std;
typedef long long ll;
int n,m,x,y,z,l;
int t[M],next[M],d[M],v[M],last[N];
ll dis[N],ans;
bool bz[N];
void add(int x,int y,ll z) {
t[++l]=y;v[l]=z;next[l]=last[x];last[x]=l;
}
void spfa() {
memset(dis,127,sizeof(dis));dis[1]=0;
memset(bz,0,sizeof(bz));bz[1]=1;
int i=0,j=1;d[1]=1;
while (i<j) {
rep(k,d[++i]) if (dis[t[k]]>dis[d[i]]+v[k]) {
dis[t[k]]=dis[d[i]]+v[k];
if (!bz[t[k]]) bz[t[k]]=1,d[++j]=t[k];
}
bz[d[i]]=0;
}
}
int main() {
freopen("cut.in","r",stdin);
freopen("cut.out","w",stdout);
scanf("%d%d",&n,&m);
fo(i,1,m) {
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);add(y,x,z);
add(x,y+n,1);add(y,x+n,1);
add(x+n,y+2*n,1);add(y+n,x+2*n,1);
add(x+2*n,y+2*n,z);add(y+2*n,x+2*n,z);
}
spfa();printf("%lld",min(dis[3*n],dis[2*n]));
}