• [POJ][3662][Telephone Lines]


    题目:http://poj.org/problem?id=3662

    题意:FJ要从1到N接电话线,电话公司可以免除K条的费用,求让需付费的电话线中的最大值在各种方案中最小的值,并输出。

    我用的是二分+Dijkstra+二次建图的方法:

    假设A是可行解,即路径上边权最大值为A,则该路径上边权大于A的边一定小于等于K条。

    若A不是最优解,那么必然B<A,是的路径上边权大于B的边小于等于K。

    于是我们可以二分答案,得到一个值X,将所有小于等于X的边变为0,大于X的边变为1。

    做最短路,则1到N的距离就是所用权值大于X边的条数。如果小于等于K,则是一个可行解。

    View Code
    #include<stdio.h>
    #include
    <algorithm>
    #include
    <queue>
    #include
    <string.h>
    //#include<conio.h>
    using namespace std;
    typedef
    int T;
    const T INF=0x3f3f3f3f;
    const int NODE_MAX = 1005;
    const int EDGE_MAX = 10000*2+5;
    T weight[NODE_MAX
    +10];
    int head[NODE_MAX+10];
    T dis[NODE_MAX
    +10];
    int vis[NODE_MAX+10];

    int sta,ed;
    int node_num,edge_num;
    int num = 0;

    int a[EDGE_MAX], b[EDGE_MAX], c[EDGE_MAX], csort[EDGE_MAX];

    struct Node
    {
    T dist;
    int sta;
    Node(){};
    Node(
    int a,T b):sta(a),dist(b){};

    bool operator<(const Node a)const
    {
    return dist > a.dist;
    }
    };

    struct Edge
    {
    int ed;
    int nxt;
    T cost;
    }edge[EDGE_MAX];

    void add_edge(int st,int ed,T cost)
    {
    edge[
    ++num].ed = ed;
    edge[num].cost
    = cost;
    edge[num].nxt
    = head[st];
    head[st]
    = num;
    }

    int dijkstra(int sta)
    {
    priority_queue
    <Node>que;
    while(!que.empty()) que.pop();
    memset(vis,
    0,sizeof(vis));
    for(int i=0;i<=node_num;i++)
    dis[i]
    = INF;
    dis[sta]
    =0;
    Node node_temp;
    que.push(Node(sta,
    0));
    while(!que.empty())
    {
    node_temp
    = que.top();
    que.pop();
    if(vis[node_temp.sta]) continue;
    vis[node_temp.sta]
    =1;
    for(int i=head[node_temp.sta]; i!=-1; i=edge[i].nxt)
    {
    if(dis[edge[i].ed] > node_temp.dist + edge[i].cost)
    {
    dis[edge[i].ed]
    = node_temp.dist + edge[i].cost;
    que.push(Node(edge[i].ed,dis[edge[i].ed]));
    }
    }
    }
    return 1;
    }


    int main()
    {
    //freopen("D:/a.txt", "r", stdin);
    int k, i, j, max, min, ans=INF, csort_num=1, ok, mid, oks=-1, flag=1;
    scanf(
    "%d%d%d", &node_num, &edge_num, &k);
    memset(csort,
    0, sizeof(csort));
    for (i=1;i<=edge_num;i++)
    {
    scanf(
    "%d%d%d", &a[i], &b[i], &c[i]);
    {
    ok
    =1;
    for (j=1;j<=csort_num;j++)
    {
    if (c[i]==csort[j])
    {
    ok
    =0;
    break;
    }
    }
    if (ok)
    csort[csort_num
    ++]=c[i];
    }
    }
    sort(csort, csort
    +csort_num);
    max
    =csort_num-1;
    min
    =0;
    while (max>=min)
    {
    memset(dis,
    0, sizeof(dis));
    memset(head,
    -1, sizeof(head));
    mid
    =(max+min)/2;
    num
    =0;
    for (i=0;i<=edge_num;i++)
    {
    if (c[i]>csort[mid])
    {
    add_edge(a[i], b[i],
    1);
    add_edge(b[i], a[i],
    1);
    }
    else
    {
    add_edge(a[i], b[i],
    0);
    add_edge(b[i], a[i],
    0);
    }
    }
    dijkstra(
    1);
    if (mid==0 || mid==csort_num-1)
    {
    flag
    =dis[node_num];
    }
    if (dis[node_num]>k)
    {
    min
    =mid+1;
    oks
    =dis[node_num];
    }
    else
    {
    if (ans>csort[mid])
    {
    ans
    =csort[mid];
    oks
    =dis[node_num];
    }
    max
    =mid-1;
    }
    }
    if (flag==0)
    printf(
    "0\n");
    else if (flag<INF && ans<INF)
    printf(
    "%d\n", ans);
    else
    printf(
    "-1\n");
    //getch();
    return 0;
    }
  • 相关阅读:
    C#之正则表达式、异常处理和委托与事件
    C#之interface接口
    C#之类与对象
    C#第一次的Hello World
    第一次用博客
    用Visual Studio 2012+Xamarin搭建C#开发Andriod的环境
    cocos2dx 3.x for lua "异步加载"实现过程
    cocos2dx 3.x c++代码打包给lua调用过程(mac)
    cocos2dx 3.x lua 网络加载并且保存资源(unix、linux)
    path类和directory类对文件的路径或目录进行操作
  • 原文地址:https://www.cnblogs.com/nigel0913/p/2171871.html
Copyright © 2020-2023  润新知