[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;
}
原文地址:https://www.cnblogs.com/nigel0913/p/2171871.html