zoukankan      html  css  js  c++  java
  • HDU

    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.

    InputThe 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 ,i  xi,yi representing an edge, and i  vi representing its length.1≤,i  xi,yi ≤n,1≤i  vi ≤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 i  ai , the nodes that Master Dong selects out.1≤i  ai ≤n,i  ai !=aj
    OutputFor every Test Case, output one integer: the answerSample 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

    题意:给定有向图,然后给一个集合,让你在这个集合选一个作为起点,一个作为终点,其最短路最小。

    思路:上次做过树上最大收益(边权为花费,顶点有价格,求最大差价),每个点连接汇点,权值为负价;每个点连接源点,权值为正价。然后跑最长路。

    此题也是一样的套路,但是起点和终点不能是同一点,所以我们需要分组。

    这里分组可以随机20次;也可以用“二进制分组法”。:

    举例说明,将1 2 3 4 进行分组,四个数的二进制形式为: 001 010 011 100
    第一次看第0位为1的数,那么A={1,3},B={2,4}
    第一次看第1位为1的数,那么A={2,3},B={1,4}
    第一次看第2位为1的数,那么A={4},B={1,2,3}
    可以看出,任意一对数字,都至少有一次机会不在同一组中。

    由于是有向图,还得反过来来一次。

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    #define ll long long
    using namespace std;
    const ll inf=1234567645893456783;
    const int maxn=100010;
    int S,T,Laxt[maxn],Next[maxn];
    int in[maxn],To[maxn],Len[maxn],a[maxn],cnt;
    ll dis[maxn],ans;
    vector<int>G[maxn];
    void add(int u,int v,int w){
        Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; Len[cnt]=w;
    }
    void SPFA()
    {
        rep(i,S,T) dis[i]=inf,in[i]=0;
        dis[S]=0; queue<int>q;
        q.push(S); in[S]=1;
        while(!q.empty()){
            int u=q.front(); q.pop();
            for(int i=Laxt[u];i;i=Next[i]){
                int v=To[i]; if(dis[u]+Len[i]<dis[v]) {
                    dis[v]=dis[u]+Len[i];
                    if(!in[v]) in[v]=1,q.push(v);
                }
            }
            for(int i=0;i<G[u].size();i++){
                int v=G[u][i]; if(dis[u]<dis[v]) {
                    dis[v]=dis[u];
                    if(!in[v]) in[v]=1,q.push(v);
                }
            }
            in[u]=0;
        }
        ans=min(ans,dis[T]);
    }
    int main()
    {
        int C,Cas=0,N,M,tot,u,v,w;
        scanf("%d",&C);
        while(C--){
            scanf("%d%d",&N,&M); T=N+1; ans=inf;
            rep(j,S,T) Laxt[j]=0; cnt=0;
            rep(i,1,M) scanf("%d%d%d",&u,&v,&w),add(u,v,w);
            scanf("%d",&tot);
            rep(i,1,tot) scanf("%d",&a[i]);
            rep(i,0,17){
                rep(j,S,T) G[j].clear();
                rep(j,1,tot)
                  if(j&(1<<i)) G[S].push_back(a[j]);
                  else G[a[j]].push_back(T);
                SPFA();
                rep(j,S,T) G[j].clear();
                rep(j,1,tot)
                  if(j&(1<<i)) G[a[j]].push_back(T);
                  else G[S].push_back(a[j]);
                SPFA();
            }
            printf("Case #%d: %lld
    ",++Cas,ans);
        }
        return 0;
    }
  • 相关阅读:
    第二天与第三天的总结
    随手写的总结关于
    第一次编程作业
    第一次博客作业
    CSS学习笔记-04 a标签-导航练习
    CSS学习笔记-03- 过渡模块之前奏篇 a标签的伪类选择器
    CSS学习笔记-02. 2D转换模块-形变中心点
    CSS学习笔记-01-2D转换模块
    从今天开始 每天记录HTML,CSS 部分的学习笔记
    回流和重绘
  • 原文地址:https://www.cnblogs.com/hua-dong/p/9824108.html
Copyright © 2011-2022 走看看