【作业存档】最小生成树的练习

来源:互联网 发布:淘宝店铺二级域名收费 编辑:程序博客网 时间:2024/06/05 08:30

记,一次非常顺利的作业。

说是顺利,但其实也用了一个晚上,一边听公共关系学的课程,一边参与小组讨论,一边磕磕绊绊地写完了。当然没有一次通过所有测试点,反而是例子都没过,不过看了看代码发现了只是粗心的锅,自己的思路没大问题。

改了一下后运行超时+一个点没过,降低了时间复杂度后还是有一个点没过,最后看了一下别人的作业也顺利地改了过来。


目标是用函数实现,在一个图中去掉一个点后,记录下来其他点获得最小生成树需要将多少不在使用的边连通的权重最大的那个点,已知一组边的两个顶点、权重、是否在使用。

等价关系算法可以直接实现非常简单,主要是问题没有考虑会有不能连通的情况,


下为代码

#include<stdio.h>#include<stdlib.h>#define INF 0x7ffffffftypedef struct Road road;//直接把边存下来struct Road{    int V1,V2;    int weight;    int isUse;};int Init(road Graph1[],road Graph0[],int V,int E);int FindCity(road Graph1[],road Graph0[], int finalV[], int V, int E1, int E0);int Find(int V,int List[]);void Union(int V1, int V2, int List[]);int main(){    int V, E, count = 0, i, E1;    int *finalV;//因为V的个数不确定,所以用了动态分配内存    road *Graph1, *Graph0;        scanf("%d%d",&V,&E);    Graph1 = (road*)malloc(sizeof(struct Road)*E);//存放目前在用的道路    Graph0 = (road*)malloc(sizeof(struct Road)*E);//存放目前不在用的道路    finalV = (int*)malloc(sizeof(int)*V);        E1 = Init(Graph1, Graph0, V, E);//初始化道路        count = FindCity(Graph1, Graph0, finalV, V, E1, E- E1);//找到最需要保护的城市        for(i = 0; i < count - 1; i++){        printf("%d ", finalV[i]+1);    }    if(count == 0)        printf("0");    else        printf("%d", finalV[i]+1);        free(finalV);    free(Graph1);    free(Graph0);    return 0;}int Init(road Graph1[],road Graph0[],int V,int E){    int i, E1 = 0, E0 = 0;    int tmpV1,tmpV2, tmpWeight,isUse;    for(i = 0; i < E; i++){        scanf("%d%d%d%d", &tmpV1, &tmpV2, &tmpWeight, &isUse);        if(isUse){            Graph1[E1].V1 = tmpV1;            Graph1[E1].V2 = tmpV2;            Graph1[E1].weight = tmpWeight;            Graph1[E1].isUse = isUse;            E1++;        }        else{            Graph0[E0].V1 = tmpV1;            Graph0[E0].V2 = tmpV2;            Graph0[E0].weight = tmpWeight;            Graph0[E0].isUse = isUse;            E0++;        }    }    return E1;}int Find(int V,int List[]){//找到和V等价的那一堆数的代表点    int tmpV = List[V];    if (tmpV < 0)        return V;    while(List[tmpV] > 0){        List[V] = List[tmpV];        V = List[V];        tmpV = List[tmpV];    }    return tmpV;}void Union(int V1, int V2, int List[]){//将包含V1和V包含2的两堆数合并    int V1head = Find(V1, List), V2head = Find(V2,List);//先找到顶点    if(List[V1head] > List[V2head]){//把size小的接到size大的上,代表点指向的内容为-size        List[V2head] += List[V1head];        List[V1head] = V2head;    }    else{        List[V1head] += List[V2head];        List[V2head] = V1head;    }}int FindCity(road Graph1[],road Graph0[], int finalV[], int V, int E1, int E0){    int i, tmpV, tmpE, costSum = 0, maxCost = 0, City = V;    int *ConnectList;//用来记录联通情况    int count = 0;        //初始化联通情况    ConnectList = (int*)malloc(sizeof(int)*V);        for(tmpV = 0; tmpV < V; tmpV++){        City = V - 1;//City用来判断是否获得最小生成树        for(i = 0; i < V; i++)            ConnectList[i] = -1;        costSum = 0;        for(tmpE = 0; tmpE < E1; tmpE++){            if((Graph1[tmpE].V1 != (tmpV + 1)) && (Graph1[tmpE].V2 != (tmpV + 1))){//在这里出过错,忘了把自己去掉                if(Find(Graph1[tmpE].V1 - 1, ConnectList) != Find(Graph1[tmpE].V2 - 1,ConnectList)){                    Union(Graph1[tmpE].V1 - 1, Graph1[tmpE].V2 - 1, ConnectList);                    City--;                }            }        }        for(tmpE = 0; tmpE < E0; tmpE++){            if((Graph0[tmpE].V1 != (tmpV + 1)) && (Graph0[tmpE].V2 != (tmpV + 1)))                if(Find(Graph0[tmpE].V1 - 1, ConnectList) != Find(Graph0[tmpE].V2 - 1,ConnectList)){                    Union(Graph0[tmpE].V1 - 1, Graph0[tmpE].V2 - 1, ConnectList);                    costSum += Graph0[tmpE].weight;                    City--;                }        }        if(City > 1)            costSum = INF;            if(costSum > maxCost){            maxCost = costSum;            count = 0;            finalV[count] = tmpV;            count++;        }        else if(costSum &&costSum == maxCost){            finalV[count] = tmpV;            count++;        }            }    free(ConnectList);        return count;    }

Battle Over Cities

It is vitally important to have all the cities connected by highways in a war. If a city is conquered by the enemy, all the highways from/toward that city will be closed. To keep the rest of the cities connected, we must repair some highways with the minimum cost. On the other hand, if losing a city will cost us too much to rebuild the connection, we must pay more attention to that city.

Given the map of cities which have all the destroyed and remaining highways marked, you are supposed to point out the city to which we must pay the most attention.

Input Specification:

Each input file contains one test case. Each case starts with a line containing 2 numbers N (\le500), and M, which are the total number of cities, and the number of highways, respectively. Then M lines follow, each describes a highway by 4 integers: City1 City2 Cost Status where City1 and City2 are the numbers of the cities the highway connects (the cities are numbered from 1 to N), Cost is the effort taken to repair that highway if necessary, and Status is either 0, meaning that highway is destroyed, or 1, meaning that highway is in use.

Note: It is guaranteed that the whole country was connected before the war.

Output Specification:

For each test case, just print in a line the city we must protest the most, that is, it will take us the maximum effort to rebuild the connection if that city is conquered by the enemy.

In case there is more than one city to be printed, output them in increasing order of the city numbers, separated by one space, but no extra space at the end of the line. In case there is no need to repair any highway at all, simply output 0.

Sample Input 1:

4 51 2 1 11 3 1 12 3 1 02 4 1 13 4 1 0

Sample Output 1:

1 2

Sample Input 2:

4 51 2 1 11 3 1 12 3 1 02 4 1 13 4 2 1

Sample Output 2:

0


0 0
原创粉丝点击