建图+最短路。新建一个特别的节点,每个城市与这个特别节点之间加上一条长为该城市停留的花费a的边;然后对于题目给出每条边,将长度设置为原来长度乘以2(因为需要一来一回两次)加入图中。这样从新建节点到每个城市的最短路就是题目所求的最短花费了。用堆优化dij求单源最短路就行了。(好像新学了一点重载运算符相关的东西)
(最近好像一直因为数组开错WA题。。啊这真是)
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define maxn 200005 #define maxm 600005 #define inf 1e13 using namespace std; typedef long long ll; int num,to[maxm],nxt[maxm],last[maxn],vis[maxn],n,m; ll w[maxm],dis[maxn]; struct node { int num; ll dis; node(int x,ll y) { num=x;dis=y; } bool operator < (const node &a)const{return dis>a.dis;} //重载运算符< }; priority_queue<node>q; void add(int x,int y,ll z) { to[++num]=y; nxt[num]=last[x]; last[x]=num; w[num]=z; } void dij(int s) { int i,x,y; for (i=1;i<=n+1;i++) { dis[i]=inf;vis[i]=0; } dis[s]=0; q.push(node(s,0)); while (!q.empty()) { x=q.top().num; q.pop(); if (vis[x]) continue; vis[x]=1; for (i=last[x];i;i=nxt[i]) { y=to[i]; if (dis[x]+w[i]<dis[y]) { dis[y]=dis[x]+w[i]; q.push(node(y,dis[y])); } } } } int main() { int i,j,x,y; ll z; scanf("%d%d",&n,&m); for (i=1;i<=m;i++) { scanf("%d%d%lld",&x,&y,&z); add(x,y,2*z); add(y,x,2*z); } for (i=1;i<=n;i++) { scanf("%lld",&z); add(n+1,i,z); } dij(n+1); for (i=1;i<=n;i++) printf("%lld ",dis[i]); return 0; }
对图求最大生成树,对于每组询问找LCA即可。(学着用了倍增求LCA,以为代码会比树链剖分短,但并没有。。)
#include<cstdio> #include<cstring> #include<algorithm> #define maxn 10005 #define maxm 100005 #define inf 99999999 using namespace std; int w[maxn][22],fa[maxn][22],dep[maxn],vis[maxn]; int num,to[maxm],nxt[maxm],last[maxn],wei[maxm]; int f[maxn]; struct edge { int from,to,w; }e[maxm]; bool cmp(edge x,edge y){return x.w>y.w;} void add(int x,int y,int z) { to[++num]=y; nxt[num]=last[x]; last[x]=num; wei[num]=z; } int find(int x) { if (x==f[x]) return x; return f[x]=find(f[x]); } void dfs(int x) { int i,y; vis[x]=1; for (i=last[x];i;i=nxt[i]) { y=to[i]; if (vis[y]) continue; dep[y]=dep[x]+1; w[y][0]=wei[i]; fa[y][0]=x; dfs(y); } } int lca(int x,int y) { if (find(x)!=find(y)) return -1; int i,ans=inf; if (dep[x]>dep[y]) { i=x;x=y;y=i; } for (i=20;i>=0;i--) if (dep[fa[y][i]]>=dep[x]) { ans=min(ans,w[y][i]); y=fa[y][i]; } if (x==y) return ans; for(i=20;i>=0;i--) { if(fa[x][i]!=fa[y][i]) { ans=min(ans,w[x][i]); ans=min(ans,w[y][i]); x=fa[x][i]; y=fa[y][i]; } } ans=min(ans,w[x][0]); ans=min(ans,w[y][0]); return ans; } int main() { int i,j,x,y,fx,fy,n,m,q; scanf("%d%d",&n,&m); for (i=1;i<=m;i++) scanf("%d%d%d",&e[i].from,&e[i].to,&e[i].w); sort(e+1,e+m+1,cmp); for (i=1;i<=n;i++) f[i]=i; for (i=1;i<=m;i++) { x=e[i].from; y=e[i].to; fx=find(x); fy=find(y); if (fx!=fy) { f[fx]=fy; add(e[i].from,e[i].to,e[i].w); add(e[i].to,e[i].from,e[i].w); } } for (i=1;i<=n;i++) { if (vis[i]) continue; dep[i]=1; fa[i][0]=i; w[i][0]=inf; dfs(i); } for (i=1;i<=20;i++) for (j=1;j<=n;j++) { fa[j][i]=fa[fa[j][i-1]][i-1]; w[j][i]=min(w[j][i-1],w[fa[j][i-1]][i-1]); } scanf("%d",&q); while (q--) { scanf("%d%d",&x,&y); printf("%d ",lca(x,y)); } return 0; }