HDU - 6166(102/600)点集之间最短路

Senior Pan fails in his discrete math exam again. So he asks Master ZKC to give him graph theory problems everyday.
The task is simple : ZKC will give Pan a directed graph every time, and selects some nodes from that graph, you can calculate the minimum distance of every pair of nodes chosen in these nodes and now ZKC only cares about the minimum among them. That is still too hard for poor Pan, so he asks you for help.
Input
The first line contains one integer T, represents the number of Test Cases.1≤T≤5.Then T Test Cases, for each Test Cases, the first line contains two integers n,m representing the number of nodes and the number of edges.1≤n,m≤100000
Then m lines follow. Each line contains three integers xi,yixi,yi representing an edge, and vivi representing its length.1≤xi,yixi,yi≤n,1≤vivi≤100000
Then one line contains one integer K, the number of nodes that Master Dong selects out.1≤K≤n
The following line contains K unique integers aiai, the nodes that Master Dong selects out.1≤aiai≤n,aiai!=aj
Output
For every Test Case, output one integer: the answer
Sample Input
1
5 6
1 2 1
2 3 3
3 1 3
2 5 1
2 4 2
4 3 1
3
1 3 5
Sample Output
Case #1: 2

这个题我是走歪了…
这个分组方式是真的服气

然后就是竟然有点集对点集最短路的板子…
服了服了

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ll long long
#define pii pair
#define pll pair
using namespace std;
const int inf = 1e9 + 7;
const int N = 100000 + 5;//顶点数
vectortu[N];
vector<int>kk;
ll daon[N];
void Dijkstra(int n, const vector<int>&s)//点集到点集的最短路板子
{
    fill(daon, daon + n + 1, 1e18);
    priority_queuevector, greater >que;
    for (int x : s) {
        daon[x] = 0;
        que.push({ daon[x],x });
    }
    while (!que.empty()) {
        int u = que.top().second;
        que.pop();
        for (const pll&e : tu[u]) {
            ll v = e.first, w = e.second;
            if (daon[v]>daon[u] + w) {
                daon[v] = daon[u] + w;
                que.push({ daon[v],v });
            }
        }
    }
}
vector<int>s, e;
int main()
{
    int T,u=0;
    cin >> T;
    while(T--)
    {
        int n, m;
        cin >> n >> m;
        for (int a = 1; a <= n; a++)tu[a].clear();
        for (int a = 1; a <= m; a++)
        {
            int q, w, e;
            scanf("%d%d%d", &q, &w, &e);
            tu[q].push_back({ w,e });
        }
        int k;
        cin >> k;
        kk.clear();
        for(int a=1;a<=k;a++)
        {
            int x;
            scanf("%d", &x);
            kk.push_back(x);
        }
        ll dan = 1e18;
        for (int a=1;a<=20;a++) 
        {
            s.clear();
            e.clear();
            for (int j : kk) 
            {
                if (j & 1<<(a-1)) s.push_back(j);
                else e.push_back(j);
            }
            Dijkstra(n, s);//从这开始
            for (auto x : e)dan = min(dan, daon[x]);
            Dijkstra(n, e);
            for (auto x : s)dan = min(dan, daon[x]);//到这里都是求点集之间最短路的
        }
        printf("Case #%d: %lld\n", ++u, dan);
    }
}

你可能感兴趣的:(ACM练习,二分,最短路)