hdu 3251 Being a Hero

来源:互联网 发布:linux哪个系统好 编辑:程序博客网 时间:2024/06/05 05:44

题目:

Being a Hero

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 678    Accepted Submission(s): 213
Special Judge


Problem Description
You are the hero who saved your country. As promised, the king will give you some cities of the country, and you can choose which ones to own!

But don't get too excited. The cities you take should NOT be reachable from the capital -- the king does not want to accidentally enter your area. In order to satisfy this condition, you have to destroy some roads. What's worse, you have to pay for that -- each road is associated with some positive cost. That is, your final income is the total value of the cities you take, minus the total cost of destroyed roads.

Note that each road is a unidirectional, i.e only one direction is available. Some cities are reserved for the king, so you cannot take any of them even if they're unreachable from the capital. The capital city is always the city number 1.
 

Input
The first line contains a single integer T (T <= 20), the number of test cases. Each case begins with three integers n, m, f (1 <= f < n <= 1000, 1 <= m < 100000), the number of cities, number of roads, and number of cities that you can take. Cities are numbered 1 to n. Each of the following m lines contains three integers u, v, w, denoting a road from city u to city v, with cost w. Each of the following f lines contains two integers u and w, denoting an available city u, with value w.
 

Output
For each test case, print the case number and the best final income in the first line. In the second line, print e, the number of roads you should destroy, followed by e integers, the IDs of the destroyed roads. Roads are numbered 1 to m in the same order they appear in the input. If there are more than one solution, any one will do.
 

Sample Input
24 4 21 2 21 3 33 2 42 4 12 34 44 4 21 2 21 3 33 2 12 4 12 34 4
 

Sample Output
Case 1: 31 4Case 2: 42 1 3
 
代码:(只解决第一步)

#include<iostream>#include<stdio.h>#include<string.h>using namespace std;const int nMax = 2505;const int INF = 0x7fffffff;int queue[nMax];//建立层次图时使用到的队列int dis[nMax];//各节点在层次图中对应的层次数struct Edge        //邻接表,包括:边的起点、边的权值、起点相同的下一条边{    int v, w, next;    Edge() {}    Edge(int v, int w, int next):v(v), w(w), next(next) {}} adj[8 * nMax];int V[nMax];//V[u]表示起点为u的第一条边,与Edge结合使用,从而实现邻接表的效果int cnt;int s, t;int min(int a, int b){    return a < b ? a : b;}void add(int u, int v, int w)//向邻接表中添加 u - > v 结构{    adj[cnt] = Edge(v, w, V[u]);    V[u] = cnt ++;    adj[cnt] = Edge(u, 0, V[v]);    V[v] = cnt ++;}int bfs()//建层次图{    int front, rear;    int v;    memset(dis, 0, sizeof(dis));    front = rear = 0;    dis[s] = 1;    queue[front ++] = s;    while(rear < front)    {        int u = queue[rear ++];        for(int i = V[u]; i != -1; i = adj[i].next)//与u相连的边            if(adj[i].w && dis[v = adj[i].v] == 0)//可通行并且 v 之间没有被访问过            {                dis[v] = dis[u] + 1;                if(v == t) return 1;                queue[front ++] = v;            }    }    return 0;}int dfs(int u, int limit = INF)//返回从u出发到t,增广路经的最小边{    if(u == t) return limit;    int count = 0;    for(int i = V[u]; i != -1; i = adj[i].next)//与u 相连的边    {        int v = adj[i].v;        if((dis[v] == dis[u] + 1) && adj[i].w)//根据层次的关系,找到的路径就为最短路径        {            int z = dfs(v, min(limit - count, adj[i].w));            if(z > 0)//增广路经的最小边不为0,即v到t可通行            {                count += z;                adj[i].w -= z;                adj[i ^ 1].w += z;//改为adj[i + 1] += z  , 会超时!            }            else                dis[v] = -1;//效果等同于删除与v相关的所有边        }    }    return count;}int dinic(){    int ans = 0;    while(bfs())//直到搜索不到增广路经为止        {int tt=dfs(s);ans += tt;}    return ans;}void init(){    cnt = 0;    memset(V, -1, sizeof(V));}int main(){    int T;    int n,m,f;    int uu,vv,ww;    //freopen("F://ACMInput/input.txt","r",stdin);    scanf("%d",&T);    for(int k=1;k<=T;k++)    {        scanf("%d%d%d",&n,&m,&f);        init();        for(int i=1;i<=m;i++)        {            scanf("%d%d%d",&uu,&vv,&ww);            add(uu,vv,ww);        }        int sum=0;        for(int i=1;i<=f;i++)        {            scanf("%d%d",&uu,&ww);            sum+=ww;            add(uu,n+1,ww);        }        s=1;t=n+1;        int ss[1000];        int ans=dinic();        printf("Case %d: %d\n",k,sum-ans);    }return 0;}


原创粉丝点击