【数字_ID】CUC Spring最小生成树图论解

Rikka with Minimum Spanning Trees Gym - 102012A

这道题是去年徐州区域赛的"签到题",也是我印象很深刻的打铁场。最小生成树计数,但是!!! 数据随机,其实就有很大概率不连通,或者只有一个最小生成树,所以就莽一发,拼人品,赌它只有一个最小生成树,那么把权值和输出就行了。(是不是很坑?是不是很坑!!)(之所以放在第一道,因为现场赛时也是A题,而且好多人都莽过去了…)

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <functional>
#include <algorithm>
#include <queue>
#include <stdio.h>
#define INF 0x7f7f7f7f
#define ull unsigned long long
using namespace std;
const int maxn = 100020;
const int MOD = 1e9+7;

ull k1,k2;
int n,m;
int fa[maxn];

void init(int n)
{
    for(int i = 0;i<=n;i++)fa[i] = i;
}
int find(int x)
{
    return (fa[x] == x)?x : fa[x] = find(fa[x]);
}
struct Edge{
    int u,v;
    ull w;
}edge[maxn];

unsigned long long xors()
{
    ull k3=k1,k4=k2;
    k1=k4;
    k3^=k3<<23;
    k2=k3^k4^(k3>>17)^(k4>>26);
    return k2+k4;
}

void gen()
{
    //scanf("%d%d%llu%llu" , &n,&m,&k1,&k2);
    scanf("%d%d%llu%llu",&n,&m,&k1,&k2);
    //cin >> n >> m >>k1 >>k2;
    for(int i = 1;i<=m;i++)
    {
        edge[i].u = xors() % n + 1;
        edge[i].v = xors() % n + 1;
        edge[i].w = xors();
    }
}

bool cmp(Edge a,Edge b)
{
    return a.w < b.w;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        gen();
        init(n);
        int ct = 0;
        ull sum = 0;
        sort(edge+1,edge+1+m,cmp);
        for(int i = 1;i<=m;i++)
        {
            int fx = find(edge[i].u);
            int fy = find(edge[i].v);
            if(fx != fy){
                ct ++;
                fa[fx] = fy;
                sum = (sum + edge[i].w)%MOD;
            }
        }
        if(ct != n-1)printf("0\n");
        else printf("%llu\n" , sum);
    }
}

Networking POJ - 1287

一个简单的最小生成树的题

#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;

const int maxn = 10020;

int fa[maxn];
int ct = 0;
int ans;
struct Edge{
    int u,v,w;
}edge[maxn];

void init(int n)
{
    ct = 0;
    ans = 0;
    for(int i = 0;i<=n;i++)
    {
        fa[i] = i;
    }
}

void addedge(int u,int v,int w)
{
    edge[ct].u = u;
    edge[ct].v = v;
    edge[ct].w = w;
    ct ++;
}
bool cmp(Edge a,Edge b)
{
    return a.w<b.w;
}

int find(int x)
{
    return (fa[x] == x)?fa[x]:fa[x] = find(fa[x]);
}
int n,m;
int main()
{
    while(cin >> n && n){
        init(n);
        cin >> m;
        for(int i = 0;i<m;i++){
            int u,v,w;
            cin >> u >> v >> w;
            addedge(u,v,w);
        }
        sort(edge,edge+ct,cmp);
        for(int i = 0;i<ct;i++)
        {
            int u = edge[i].u , v = edge[i].v;
            int fx = find(u) , fy = find(v);
            if(fx != fy){
                fa[fx] = fy;
                ans += edge[i].w;
            }
        }
        cout << ans << endl;
    }
}

最短路径·一 HihoCoder - 1081

最短路裸题,我用dijk写的

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <functional>
#include <algorithm>
#include <queue>
#define INF 0x7f7f7f7f
using namespace std;

const int maxn = 10020;

int ct = 0;
int ans;
int n,m,s,t;
int head[maxn];
int dis[maxn];
struct {
    int v , w , next;
}edge[2*maxn];

struct node{
    int x;
    int dis;
    bool operator < (const node b)const{
        return dis > b.dis;
    }
};


void init(int n)
{
    for(int i = 0;i<=n;i++)head[i] = -1 ,dis[i] = INF ;
    ct = 0;
}

void addedge(int u,int v,int w)
{
    edge[ct].v = v;
    edge[ct].w = w;
    edge[ct].next = head[u];
    head[u] = ct++;
}

void dijk(int now)
{
    node st;
    st.x = now;
    st.dis = 0;
    dis[now] = 0;
    priority_queue<node>Q;
    Q.push(st);
    while(!Q.empty())
    {
        node t = Q.top();
        Q.pop();
        if(dis[t.x] != t.dis)continue;
        for(int i = head[t.x];~i;i = edge[i].next)
        {
            int to = edge[i].v;
            if(dis[t.x] + edge[i].w < dis[to]){
                dis[to] = dis[t.x] + edge[i].w;
                //cout << "to = " << to << " , dis[to] = " <<dis[to] << endl;
                Q.push((node){to , dis[to]});
            }
        }
    }

}
int main()
{
    int T;
    //cin >> T;
    //for(int tt = 1;tt<=T;tt++)
   // {
        cin >> n >> m >> s >>t;
        init(n);
        for(int i = 0;i<m;i++)
        {
            int u,v,w;cin >> u >> v >>w;
            addedge(u,v,w);
            addedge(v,u,w);
            //cout << "fuck" <<endl;
        }
        dijk(s);
        cout << dis[t] << endl;
   // }
}

最短路径·二:Floyd算法 HihoCoder - 1089

裸题,希望可以自己实现,非常好记

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<queue>
#define clr(x,b) memset(x,(b),sizeof(x))
#define fuck cout<<"fuck:"<<__LINE__<<____endl
#define MOD (ll)(1e9+7)

using namespace std;

const int maxn = 120;
const int maxm = 1020;
int _mp[maxn][maxn];
int n,m;
int main()
{
	cin>>n>>m;
	clr(_mp,0x3f3f3f3f);
	for(int i = 0;i<=n;i++)_mp[i][i] = 0;
	for(int i = 0;i<m;i++){
		int u,v,l;cin>>u>>v>>l;
		if(_mp[u][v]>l){
			_mp[u][v] = l;
			_mp[v][u] = l;
		}
	}
	for(int k = 1;k<=n;k++){
		for(int i = 1;i<=n;i++){
			for(int j = 1;j<=n;j++){
				_mp[i][j] = min(_mp[i][j],_mp[i][k]+_mp[k][j]);
			}
		}
	}
	for(int i = 1;i<=n;i++){
		for(int j = 1;j<=n;j++){
			cout<<_mp[i][j]<<" ";
		}
		cout<<endl;
	}
}

最短路径·三:SPFA算法 HihoCoder - 1093

也可以用别的方法,这里我是为了练习spfa,所以用的spfa

#include<iostream>
#include<algorithm>
#include<string.h>
#include<string>
#include<queue>
#include<vector>
#define clr(x,b) memset(x,(b),sizeof(x))
#define fuck cout<<"fuck:"<<__LINE__<<endl;
using namespace std;

const int maxn = 1e5+21;
const int maxm  = 1e6+20;
int S,T,n,m;
int ct = 0;
int dis[maxn];
bool inq[maxn];
int num[maxn];
int head[maxn];
struct edge{
	int to;
	int len;
	int next;
}E[maxm]; 
struct node{
	int x;
	int dis;
	bool operator < (const node b)const{
		return dis<b.dis;
	}
};
void addedge(int u,int v,int w){
	E[ct].to = v;
	E[ct].len = w;
	E[ct].next = head[u];
	head[u] = ct++;
}

void spfa(){
	queue<int>Q;
	Q.push(S);
	inq[S] = true;
	dis[S] = 0;
	num[S]++;
	while(!Q.empty()){
		int t = Q.front();
		Q.pop();
		inq[t] = false;
		for(int i = head[t];i!=-1;i = E[i].next){
			int x = E[i].to;
			int l = E[i].len;
			if(dis[x]>dis[t]+l){
				dis[x] = dis[t]+l;
				if(!inq[x]){
					inq[x] = true;
					Q.push(x);
					num[x] ++ ;
					if(num[x]>n)return;
				}
			}
		}
	}
}


int main(){
	ct = 0;
	clr(head,-1);
	clr(inq,0);
	clr(dis,0x3f3f3f3f);
	clr(num,0);
	cin>>n>>m>>S>>T;
	for(int i = 0;i<m;i++){
		int u,v,l;cin>>u>>v>>l;
		addedge(u,v,l);
		addedge(v,u,l);
	}
	spfa();
	//fuck
	cout<<dis[T]<<endl;

}

最小生成树一·Prim算法 HihoCoder - 1097

#include<iostream>
#include<algorithm>
#include<string.h>
#include<string>
#include<queue>
#include<vector>
#define clr(x,b) memset(x,(b),sizeof(x))
#define fuck cout<<"fuck:"<<__LINE__<<endl;
#define INF 0x3f3f3f3f
using namespace std;

const int maxn = 1020;
bool visit[maxn];
int dis[maxn];
int G[maxn][maxn];
int ans = 0;
int n;
void prim(){
	dis[1] = 0;
	for(int i = 0;i<n;i++){
		int mn = INF;
		int pos = 0;
		for(int j = 1;j<=n;j++){
			if(visit[j])continue;
			if(dis[j]<mn){
				mn = dis[j];
				pos = j;
			}
		}
		if(pos == 0)break;
		visit[pos] = true;
		ans += dis[pos];
		//dis[pos] = 0;
		for(int j = 1;j<=n;j++){ 
			dis[j] = min(dis[j],G[pos][j]);
		} 
	}
}
int main(){
	clr(dis,INF);
	cin>>n;
	for(int i = 1;i<=n;i++){
		for(int j = 1;j<=n;j++){
			int a;cin>>a;
			G[i][j] = a;
		}
	}
	prim();
	//fuck
	cout<<ans<<endl;
}

最小生成树二·Kruscal算法 HihoCoder - 1098

#include<iostream>
#include<algorithm>
#include<string.h>
#include<string>
#include<queue>
#include<vector>
#define clr(x,b) memset(x,(b),sizeof(x))
#define fuck cout<<"fuck:"<<__LINE__<<endl;
using namespace std;

const int maxm = 1e6+20;
const int maxn = 1e5+20;
struct edge{
	int u;
	int v;
	int len;
}E[maxm];

bool cmp(edge a,edge b){
	return a.len<b.len;
}
bool visit[maxm];
int fa[maxn];
int n,m;
void init(){
	for(int i = 0;i<=n;i++)fa[i] = i;
}
int find(int x){
	return (fa[x] == x)?x:fa[x] = find(fa[x]);
}

void join(int a,int b){
	int x = find(a);
	int y = find(b);
	if(x!=y)fa[x] = y;
}

int main()
{
	cin>>n>>m;
	clr(visit,0);
	init();
	for(int i = 0;i<m;i++){
		cin>>E[i].u>>E[i].v>>E[i].len;
	}
	sort(E,E+m,cmp);
	int ans = 0;
	for(int i = 0;i<m;i++){
		int u = E[i].u;
		int v = E[i].v;
		int l = E[i].len;
		int x = find(u);
		int y = find(v);
		if(x!=y){
			fa[x] = y;
			ans += l;
		}
		else continue;
	}
	cout<<ans<<endl;
}

Heavy Transportation POJ - 1797

从1到n的所有路径中,输出最小值最大的路径的最小值,dijk变一下,用dis维护到当前点的最小值,每次更新时dis[x] = max(dis[t] , min(edte[i].w,dis[t.x]));,记得优先队列中弹出的点事是离源点路径中最小值最大的点

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <functional>
#include <algorithm>
#include <queue>
#include <stdio.h>
#define INF 0x7f7f7f7f
using namespace std;

const int maxn = 20020;
const int maxm = 1000020;
int ct = 0;
int ans;
int n,m,s,t;
int head[maxn];
int dis[maxn];
struct {
    int v , w , next;
}edge[2*maxm];

struct node{
    int x;
    int dis;
    bool operator < (const node b)const{
        return dis < b.dis;
    }
};


void init(int n)
{
    for(int i = 0;i<=n;i++)head[i] = -1 ,dis[i] = 0 ;
    ct = 0;
}

void addedge(int u,int v,int w)
{
    edge[ct].v = v;
    edge[ct].w = w;
    edge[ct].next = head[u];
    head[u] = ct++;
}

void dijk(int now)
{
    node st;
    st.x = now;
    st.dis = INF;
    dis[now] = INF;
    priority_queue<node>Q;
    Q.push(st);
    while(!Q.empty())
    {
        node t = Q.top();
        Q.pop();
       // cout << t.x << endl;
        if(dis[t.x] > t.dis)continue;
        for(int i = head[t.x];~i;i = edge[i].next)
        {
            int to = edge[i].v;
            if(min(dis[t.x] , edge[i].w) > dis[to]){
                dis[to] = min(dis[t.x] , edge[i].w);
                //cout << "to = " << to << " , dis[to] = " <<dis[to] << endl;
                Q.push((node){to , dis[to]});
            }
        }
    }

}
int main()
{
    int T;
    scanf("%d" , &T);
    for(int tt = 1;tt<=T;tt++)
    {
        //cin >> n >> m ;
        scanf("%d%d" , &n , &m);
        init(n);
        for(int i = 0;i<m;i++)
        {
            int u,v,w;//cin >> u >> v >>w;
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w);
            addedge(v,u,w);
            //cout << "fuck" <<endl;
        }
        dijk(1);
        printf("Scenario #%d:\n%d\n\n",tt,dis[n]);
        //cout << dis[n] << endl;
    }
}

还是畅通工程 HDU - 1233

一个简单的最小生成树题

#include<iostream>
#include <algorithm>
using namespace std;
int n,ans;
int f[120];
typedef struct _fff
{
    int from,to,dis;
}FFF;
FFF edge[5020];
bool cmp(FFF a,FFF b)
{
    return a.dis < b.dis;
}
int find(int x)
{
    if(x!=f[x])f[x] = find(f[x]);
    return f[x];
}
void Union(int a,int b,int i)
{
    int x = find(a);
    int y = find(b);
    if(x == y)return;
    ans += edge[i].dis;
    f[y] = x;
}
int main()
{
    cin>>n;
    while(n)
    {
        ans = 0;
        for(int i=1;i<=n;i++)f[i] = i;
        int k =n*(n-1)/2;
        for(int i=0;i<k;i++)
        {
            cin>>edge[i].from>>edge[i].to>>edge[i].dis;
        }
        sort(edge,edge+k,cmp);
        for(int i = 0;i<k;i++)
        {
            Union(edge[i].from,edge[i].to,i);
        }
        cout<<ans<<endl;
        cin>>n;
    }
}

畅通工程再续 HDU - 1875

在最小生成树的基础上加了一下距离限制,多个if条件即可

# include <iostream>
# include <stdio.h>
# include <string.h>
# include <algorithm>
# include <math.h>
# include <queue>
# include <string>
# include <vector>
# include <set>
# include <map>
# define INF 0x3f3f3f3f
# define clr0(x) memset(x,0,sizeof(x))
# define clr1(x) memset(x,INF,sizeof(x))
# define clrf(x) memset(x,-1,sizeof(x))
# define rep(i,a) for(int i = 0;i<(a);i++)
# define repf(i,a,b) for(int i = (a);i<=(b);i++)
# define repu(i,a,b) for(int i = (a);i<(b);i++)
# define repd(i,a,b) for(int i = (a);i>=(b);i--)
# define lowbit x&(-x)
# define ww(a) while(a)
# define sc(x) scanf("%d",&(x))
# define sd(x) scanf("%I64d",&(x))
# define lson(x) (x)<<1
# define rson(x) (x)<<1|1
# define ll long long
# define fuckio ios::sync_with_stdio(false);
# define fuck cout<<"fuck:"<<__LINE__<<endl;
# define gcd(a,b) __gcd((a),(b))
# define maxn 120
using namespace std;


int fa[maxn];
int xx[maxn];
int yy[maxn];
int n,m,cnt,num;
void init()
{
    repf(i,0,n)fa[i] = i;
    cnt = 0;
    num = 0;
}

int find(int x)
{
    return (fa[x] == x)?x:fa[x] = find(fa[x]);
}

struct edge
{
    int u;
    int v;
    double len;
}E[maxn*maxn];

bool cmp(edge a,edge b)
{
    return a.len<b.len;
}


double kruskal()
{
    double ret = 0;
    rep(i,cnt){
        int fu = find(E[i].u);
        int fv = find(E[i].v);
        if(fu!=fv){
            fa[fu] = fv;            
            ret += E[i].len;
            num ++;
        }
    }
    return ret;
}
int main()
{
    int T;sc(T);
    ww(T--){
        sc(n);
        init();
        repf(i,1,n){
            scanf("%d%d",&xx[i],&yy[i]);
        }
        repf(i,1,n){
            repf(j,1,n){
                double tmp =sqrt((xx[i]-xx[j])*(xx[i]-xx[j])+(yy[i]-yy[j])*(yy[i]-yy[j]));
                if(tmp>=10&&tmp<=1000){
                    E[cnt].u = i;
                    E[cnt].v = j;
                    E[cnt++].len = tmp;       
                }
            }
        }
        sort(E,E+cnt,cmp);
        double ans = kruskal()*100;
        if(num!=n-1)printf("oh!\n");
        else printf("%.1lf\n",ans);
    }
}

地铁 CSU - 1808

每个点是地铁站,每个边表示属于几号线,现在有个代价是,如果路线中相邻的两个边属于的号线不一样,就需要有额外的 ∣ c i − c j ∣ |c_{i} - c_{j}| cicj的换乘代价,问你从1号点到n号店的最小代价。我们这里需要加一个stt[maxn]数组又来记录,从原点到当前点,最后一次的乘车时几号线,然后维护最小值dis[to] = min(dis[to],edge[i].w + dis[t.x] + abs(stt[t.x] - edge[i].sta));。因为源点出发的时候,没有换乘,所以单独考虑。

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <functional>
#include <algorithm>
#include <queue>
#include <stdio.h>
#define INF 0x7f7f7f7f
using namespace std;

const int maxn = 200020;
const int maxm = 200020;
int ct = 0;
int ans;
int n,m,s,t;
int head[maxn];
int dis[maxn];
int stt[maxn];
struct {
    int v , w ,next ,  sta;
}edge[2*maxm];

struct node{
    int x;
    int dis;
    bool operator < (const node b)const{
        return dis > b.dis;
    }
};


void init(int n)
{
    for(int i = 0;i<=n;i++)head[i] = -1 ,dis[i] = INF ,stt[i] = 0;;
    ct = 0;
}

void addedge(int u,int v,int w,int sta)
{
    edge[ct].v = v;
    edge[ct].w = w;
    edge[ct].next = head[u];
    edge[ct].sta = sta;
    head[u] = ct++;
}

void dijk(int now)
{
    node st;
    st.x = now;
    st.dis = 0;
    stt[now] = INF;
    dis[now] = 0;
    priority_queue<node>Q;
    Q.push(st);
    while(!Q.empty())
    {
        node t = Q.top();
        Q.pop();
       // cout << t.x << endl;
        if(dis[t.x] < t.dis)continue;
        for(int i = head[t.x];~i;i = edge[i].next)
        {
            int to = edge[i].v;

            if(stt[t.x] == INF && edge[i].w + dis[t.x] < dis[to]){
                dis[to] = edge[i].w + dis[t.x] ;
                stt[to] = edge[i].sta;
                //cout << "to = " << to << " , dis[to] = " <<dis[to] << endl;
                Q.push((node){to , dis[to]});
            }else if(edge[i].w + dis[t.x] + abs(stt[t.x] - edge[i].sta) < dis[to]){
                dis[to] = edge[i].w + dis[t.x] + abs(stt[t.x] - edge[i].sta);
                stt[to] = edge[i].sta;
                Q.push((node){to , dis[to]});
            }
        }
    }

}
int main()
{
    while(~scanf("%d%d",&n,&m)){
        init(n);
        for(int i = 0;i<m;i++){
            int u,v,w,c;
            scanf("%d%d%d%d",&u,&v,&c,&w);
            addedge(u,v,w,c);
            addedge(v,u,w,c);
        }
        dijk(1);
        printf("%d\n",dis[n]);
    }
}

Wormholes POJ - 3259

给一个图,和一些权值为正的边,一些权值为负的边,权值为负的边是单向的,正的是双向的,问你有没有负环,我直接用spfa判断,如果有的点被访问次数大于n次,则说明产生了负环

#include<iostream>
#include<algorithm>
#include<string.h>
#include<string>
#include<queue>
#include<vector>
#include<map>
#define clr(x,b) memset(x,(b),sizeof(x))
#define fuck cout<<"fuck:"<<__LINE__<<endl;
using namespace std;

const int maxn = 100200;
const int maxm  = 100200;
int n,m,w;
int ct = 0;
int dis[maxn];
bool inq[maxn];
int head[maxn];
int num[maxn];
struct edge{
	int to;
	int len;
	int next;
}E[maxm]; 
struct node{
	int x;
	int dis;
	bool operator < (const node b)const{
		return dis<b.dis;
	}
};
void addedge(int u,int v,int w){
	E[ct].to = v;
	E[ct].len = w;
	E[ct].next = head[u];
	head[u] = ct++;
}

bool spfa(){
	queue<int>Q;
	int st = 1;
	dis[st] = 0;
	Q.push(st);
	inq[st] = true;
	num[st]++;
	while(!Q.empty()){
		
		int t = Q.front();
		Q.pop();
		inq[t] = false;
		for(int i = head[t];i!=-1;i = E[i].next){
			int d = E[i].to;
		//	if(inq[d])continue;
			if(dis[d]>dis[t]+E[i].len){
				//fuck
				dis[d] = dis[t]+E[i].len;
				if(!inq[d]){
					inq[d] = true;
					Q.push(d);
					num[d]++;
					if(num[d]>n)return true;
				}
				
			}
		}
	}
	return false;
}
int main(){
	int T;
	cin>>T;
	while(T--){
		clr(head,-1);
		ct = 0;
		clr(dis,0x3f3f3f3f);
		clr(num,0);
		clr(inq,0);
		cin>>n>>m>>w;
		for(int i = 0;i<m;i++){
			int u,v,l;cin>>u>>v>>l;
			addedge(u,v,l);
			addedge(v,u,l);
		}
		for(int i = 0;i<w;i++){
			int u,v,l;cin>>u>>v>>l;
			addedge(u,v,-l);
		}
		if(spfa())cout<<"YES"<<endl;
		else cout<<"NO"<<endl;
	}


	//fuck
	
	
}

飞行路线 HYSBZ - 2763

分层最短路 , 假设如果可以选择k个路,我们就想象有(k+1)个平行宇宙,每个平行宇宙的图是一样的,平行宇宙相邻两层之间的边权值为0,每次决定是否选择这条边,就意味着从这一层到达上一层,最后输出(k+1)个平行宇宙中的最小值即可,具体看建图那一块的代码

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <functional>
#include <algorithm>
#include <queue>
#include <stdio.h>
#define INF 0x7f7f7f7f
using namespace std;

const int maxn = 110020;
const int maxm = 1100020;
int ct = 0;
int ans;
int n,m,s,t,k;
int head[maxn];
int dis[maxn];
int stt[maxn];

struct Edge{
    int v , w ,next;
}edge[2*maxm];

struct node{
    int x;
    int dis;
    bool operator < (const node b)const{
        return dis > b.dis;
    }
};


void init(int n)
{
    for(int i = 0;i<=n;i++)head[i] = -1 ,dis[i] = INF ;
    ct = 0;
}

void addedge(int u,int v,int w)
{
    edge[ct].v = v;
    edge[ct].w = w;
    edge[ct].next = head[u];
    head[u] = ct++;
}

void dijk(int now)
{
    node st;
    st.x = now;
    st.dis = 0;
    dis[now] = 0;
    priority_queue<node>Q;
    Q.push(st);
    while(!Q.empty())
    {
        node t = Q.top();
        Q.pop();
       // cout << t.x << endl;
        if(dis[t.x] != t.dis)continue;
        for(int i = head[t.x];~i;i = edge[i].next)
        {
            int to = edge[i].v;
            if(dis[t.x] + edge[i].w < dis[to]){
                dis[to] = dis[t.x] + edge[i].w;
                Q.push((node){to,dis[to]});
            }
        }
    }

}
int main()
{
    while(~scanf("%d%d%d",&n,&m,&k)){
        init((k+1)*(n));
        scanf("%d%d",&s,&t);
        for(int i = 0;i<m;i++)
        {
            int u,v,w;
            scanf("%d%d%d" , &u,&v,&w);
            for(int j = 0;j<=k;j++)
            {
                addedge(u + j*n , v+j*n , w);
                addedge(v + j*n , u+j*n , w);
                if(j){

                    addedge(u+(j-1)*n , v+j*n , 0);
                    addedge(v+(j-1)*n , u+j*n , 0);
                }
            }
        }

        dijk(s);
        int mn = INF;

        for(int i = 0;i<=k;i++){
            //cout << dis[t + i*n] << endl;
            mn = min(mn , dis[t + i*n]);
        }
        printf("%d\n" , mn);

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值