• SGU 323 Aviamachinations


    Aviamachinations

    Time Limit: 4500ms
    Memory Limit: 65536KB
    This problem will be judged on SGU. Original ID: 323
    64-bit integer IO format: %I64d      Java class name: Solution
     
    Berland consists of N towns as you probably already know. Berland also has M domestic airlines. In fact all these airlines belong to Don Berlione. Don Berlione was forced to create a number of companies instead of just one by the Antimonopoly Committee. 

    The Antimonopoly Committee was disbanded as a result of a government crisis. So, Don Berlione decided to close all but one airline. Naturally, this company should have flights (possibly including stopovers) from any town of Berland to any other one. To be able to choose the airline satisfying the above requirement, Don Berlione decided to carry out a number of fake purchase-sell operations. During a purchase-sell operation a flight of one airline is passed under the control of another airline. A purchase-sell operation is just a money transfer from one pocket to another. But still a special tax should be paid to the government for each operation.

    So each flight is characterized by two towns it connects, the airline it belongs to and the tax amount that should be paid for a purchase-sell operation.

    Your task is to find P — the minimum possible amount of money Don Berlione needs to spend to make it possible to leave only one airline carrying out flights (possibly with stopovers) from each town of Berland to any other. Also you need to suggest a plan of actions for Don Berlione.

     

    Input

    The first line of the input file contains three integer numbers NMK (1 ≤ N ≤ 2000; 1 ≤ M ≤ 2000; 0 ≤ K ≤ 200000), where N is the number of towns, M is the number of airlines, K is the number of flights. Each of the following K lines contains the description of the flight given by four integer numbers aibicipi, where aibi (ai != bi; 1≤ aibi≤ N) are the numbers of towns connected by the flight (towns are numbered from 1 to N), ci (1≤ ci≤ M) is the number of the airline owning the flight (airlines are numbered from 1 to M), pi (1≤ pi≤ 100000) is the tax amount required for the purchase-sell operation of the flight. Originally all flights are planned in such a way that it is possible to get from each town to any other using flights of one or several airlines. There can be several flights between a pair of towns.

     

    Output

    Write the desired minimum amount of money P to the first line of the output. After that write a pair of numbers R and Q to the same line, where R is the index of an airline which should be chosen by Don and Q is the number of purchase-sell operations. Write the description of operations to the following Q lines. Each operation should be characterized by a single integer number idxj, which means that the flight idxj should be sold to the company R. If there are several solutions for the problem, choose any of them.

     

    Sample Input

    Example(s)
    sample input
    sample output
    4 3 4
    2 3 1 6
    4 3 2 7
    1 2 2 3
    1 3 3 5
    5 2 1
    4

     


    解题:最小生成树的妙用啊。。。
     通过枚举航空公司,判断是否连通,不连通,用最小生成树中的边补连通。。。妙哉
     
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 600000;
     4 class ARC {
     5 public:
     6     int u,v;
     7     ARC(int x = 0,int y = 0) {
     8         u = x;
     9         v = y;
    10     }
    11 };
    12 class ARC1:public ARC {
    13 public:
    14     int w,id;
    15     ARC1(int x = 0,int y = 0,int cw = 0,int cid = 0):ARC(x,y) {
    16         w = cw;
    17         id = cid;
    18     }
    19     bool operator<(const ARC1 &t) {
    20         return w < t.w;
    21     }
    22 } g[maxn];
    23 class ARC2:public ARC {
    24 public:
    25     int next;
    26     ARC2(int x = 0,int y = 0,int nxt = -1):ARC(x,y) {
    27         next = nxt;
    28     }
    29 } e[maxn];
    30 int head[maxn],uf[maxn],tot,n,m,k;
    31 void init() {
    32     for(int i = 0; i <= n; ++i) uf[i] = i;
    33 }
    34 int Find(int x) {
    35     return uf[x] = x == uf[x]?x:Find(uf[x]);
    36 }
    37 void add(int u,int v,int x) {
    38     e[tot] = ARC2(u,v,head[x]);
    39     head[x] = tot++;
    40 }
    41 vector<int>MST,ans,tans;
    42 void Kruskal() {
    43     init();
    44     MST.clear();
    45     sort(g,g+k);
    46     for(int i = 0; i < k; ++i) {
    47         int x = Find(g[i].u),y = Find(g[i].v);
    48         if(x == y) continue;
    49         uf[x] = y;
    50         MST.push_back(i);
    51         if(MST.size() >= n-1) return;
    52     }
    53 }
    54 void solve() {
    55     int sum = 0x3f3f3f3f,id,tsum;
    56     for(int i = 1; i <= m; ++i) {
    57         init();
    58         tans.clear();
    59         for(int j = head[i]; ~j; j = e[j].next) {
    60             int x = Find(e[j].u),y = Find(e[j].v);
    61             if(x != y) uf[x] = y;
    62         }
    63         for(int j = tsum = 0; j < MST.size(); ++j) {
    64             int x = Find(g[MST[j]].u),y = Find(g[MST[j]].v);
    65             if(x == y) continue;
    66             tsum += g[MST[j]].w;
    67             uf[x] = y;
    68             tans.push_back(MST[j]);
    69         }
    70         if(tsum < sum) {
    71             sum = tsum;
    72             id = i;
    73             ans.clear();
    74             std::copy(tans.begin(),tans.end(),std::back_inserter(ans));
    75         }
    76     }
    77     printf("%d %d %d
    ",sum,id,ans.size());
    78     bool flag = false;
    79     sort(ans.begin(),ans.end());
    80     for(int i = 0; i < ans.size(); ++i) {
    81         if(flag) putchar(' ');
    82         printf("%d",g[ans[i]].id);
    83         flag = true;
    84     }
    85     putchar('
    ');
    86 }
    87 int main() {
    88     int a,b,c,p;
    89     scanf("%d %d %d",&n,&m,&k);
    90     memset(head,-1,sizeof(head));
    91     for(int i = tot = 0; i < k; ++i) {
    92         scanf("%d %d %d %d",&a,&b,&c,&p);
    93         g[i] = ARC1(a,b,p,i + 1);
    94         add(a,b,c);
    95     }
    96     Kruskal();
    97     solve();
    98     return 0;
    99 }
    View Code
  • 相关阅读:
    改造MFC程序,使原来不支持winsocket的工程支持winsocket
    算术移位和逻辑移位实现分析
    MFC 编辑框中字体大小改变,行高不能改变,只能显示一半的问题,已解决。
    在MFC中,使用控制台Console输出调试信息
    在MFC中使用GDI+的一般方法,以VC6.0编译器为例
    WinForm 实现主程序(exe)与其关联类库(*.dll)分开存放
    Deserializing/Serializing SOAP Messages in C#
    List分页
    ConvertJavaMiliSecondToDateTime
    中文数字大小写转阿拉伯数字
  • 原文地址:https://www.cnblogs.com/crackpotisback/p/4370037.html
Copyright © 2020-2023  润新知