• POJ 1511


    Description

    n-1个人从1号点出发,到剩余n-1个宣传点,然后再回到1号点汇报结果,求所有人往返路径和的最小值

    Input
    输入由T个案例组成。输入的第一行只包含正整数T。
    接下来是N和M,1 <= N,M <= 1000000,表示N个点和连接N个点的M条边。
    然后有M行,每行包括三个值U,V,W,表示从点U到点V需要W的路程。你可以假设该图连通。
    注意是单向通道!!!

    Output
    对于每个案例,打印一行,表示路径总和的最小值。

    Sample Input

    2
    2 2
    1 2 13
    2 1 33
    4 6
    1 2 10
    2 1 60
    1 3 20
    3 4 10
    2 4 5
    4 1 50

    Sample Output

    46
    210

    题目大意:

    输入一个 t 表示 t 组数据,对于每组数据,输入n和m,表示有n个顶点和m条有向边,你需要输出所有人往返路径和的最小值。

    解题思路:

    链式前向星存图 + 反向建图 + spfa,题目中提到了往返一次,说明这道题建图时建正反两个,这里使用链式前向星存图,跑两次spfa最后取{min(dis[i] + dis1[i])} 即可,注意数据范围可能很大,开long lonng ,不开wa了一次。

    Code:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <iomanip>
    #include <sstream>
    #include <cmath>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #define lowbit(x) x & (-x)
    
    using namespace std;
    
    typedef long long ll;
    typedef pair<int, int> pii;
    
    const int mod = 1e9 + 7;
    const int inf = 0x3f3f3f3f;
    const int N = 1e6 + 50;
    const int M = 1e4 + 50;
    
    int h[N], ne[N], e[N], idx;
    int h1[N], ne1[N], e1[N], idx1;
    ll w[N], w1[N];
    ll dis[N], dis1[N];
    bool vis[N];
    int T, n, m;
    
    void add(int a, int b, ll c)//正向反向各建一个图
    {
    	e[idx] = b;
    	w[idx] = c;
    	ne[idx] = h[a];
    	h[a] = idx++;
    
    	e1[idx1] = a;
    	w1[idx1] = c;
    	ne1[idx1] = h1[b];
    	h1[b] = idx1++;
    }
    
    void init()//多组数据不要忘记初始化
    {
    	idx = idx1 = 0;
    	memset(h, -1, sizeof h);
    	memset(h1, -1, sizeof h1);
    }
    
    void spfa(int s)
    {
    	memset(dis, 0x3f, sizeof dis);
    	dis[s] = 0;
    
    	queue<int > q;
    	q.push(s);
    
    	memset(vis, false, sizeof vis);
    	vis[s] = true;
    
    	while (!q.empty())
    	{
    		int t = q.front();
    		q.pop();
    
    		vis[t] = false;
    
    		for (int i = h[t]; ~i; i = ne[i])
    		{
    			int j = e[i];
    			if (dis[t] + w[i] < dis[j])
    			{
    				dis[j] = dis[t] + w[i];
    				if (!vis[j])
    				{
    					q.push(j);
    					vis[j] = true;
    				}
    			}
    		}
    	}
    }
    
    void respfa(int s)
    {
    	memset(dis1, 0x3f, sizeof dis1);
    	dis1[s] = 0;
    
    	queue<int > q;
    	q.push(s);
    
    	memset(vis, false, sizeof vis);
    	vis[s] = true;
    
    	while (!q.empty())
    	{
    		int t = q.front();
    		q.pop();
    
    		vis[t] = false;
    
    		for (int i = h1[t]; ~i; i = ne1[i])
    		{
    			int j = e1[i];
    			if (dis1[t] + w1[i] < dis1[j])
    			{
    				dis1[j] = dis1[t] + w1[i];
    				if (!vis[j])
    				{
    					q.push(j);
    					vis[j] = true;
    				}
    			}
    		}
    	}
    }
    
    int main()
    {
    	scanf("%d", &T);
    	
    	while (T --)
    	{
    		init();
    
    		scanf("%d%d", &n, &m);
    
    		while (m --)
    		{
    			int a, b;
    			ll c;
    			scanf("%d%d%lld", &a, &b, &c);
    			add(a, b, c);
    		}
    
    		spfa(1);//建好图之后跑两遍spfa即可
    		respfa(1);
    
    		ll ans = 0;//最后答案会爆int
    		for (int i = 1; i <= n; i++) ans += dis[i] + dis1[i];
    
    		printf("%lld
    ", ans);
    	}
    
    	return 0;
    }
    
  • 相关阅读:
    Chapter 1 First Sight——8
    Chapter 1 First Sight——7
    Chapter 1 First Sight——6
    Chapter 1 First Sight——5
    PAT1012
    Chapter 1 First Sight——4
    Chapter 1 First Sight——3
    需要注意的subList方法!和substring是不一样的!从源码解释他们的不同。
    餐桌项目删除餐桌
    addEventListener()绑定事件的对象方法。
  • 原文地址:https://www.cnblogs.com/Hayasaka/p/14294124.html
Copyright © 2020-2023  润新知