#bzoj3379#小G的烦恼（枚举顺序）

【问题描述】

现在 MZ 告诉你了 N-1 个她想要去的城市，MZ 初始时在号位置，并且告诉了你所有航线的两个价格。想要知道，最小的花费。

【输入】

【输出】

【样例输入】

5 5

1 2 3 2

1 3 2 4

2 4 4 2

5 3 3 3

1 4 0 1

【样例输出】

7

【样例解释】

【数据范围】

（外层二分p内q，外层二分q内p，然后两者取min好像也不是特别好说明为什么就能过，而且这题数据水）

Code：

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

const int Maxn = 2000;
const int Maxm = 5000;
const int INF = 0x3f3f3f3f;

struct FF{
int cost, pos;
bool operator < (const FF & X) const{
return cost < X.cost;
}
bool operator == (const FF & X) const{
return cost == X.cost;
}
}P[Maxm + 5], Q[Maxm + 5];
struct node{
int u, v, p, q;
}Flt[Maxm + 5];
struct E{
int v, nxt;
}edge[(Maxm << 1) + 5];

int N, M, cnt;
int fir[Maxn + 5];
bool vis[Maxn + 5];

bool getint(int & num){
char c;	int flg = 1;	num = 0;
while((c = getchar()) < '0' || c > '9'){
if(c == '-')	flg = -1;
if(c == -1)	return 0;
}
while(c >= '0' && c <= '9'){
num = num * 10 + c - 48;
if((c = getchar()) == -1)	return 0;
}
num *= flg;
return 1;
}

edge[++ cnt].v = b, edge[cnt].nxt = fir[a], fir[a] = cnt;
edge[++ cnt].v = a, edge[cnt].nxt = fir[b], fir[b] = cnt;
}

void Dfs(int x){
vis[x] = 1;
for(int i = fir[x]; i; i = edge[i].nxt)	if(! vis[edge[i].v])
Dfs(edge[i].v);
}

bool Check(int p, int q){
for( ; q <= M && Q[q].cost == Q[q + 1].cost; ++ q);
for( ; p <= M && P[p].cost == P[p + 1].cost; ++ p);
cnt = 0;
memset(fir, 0, sizeof fir );
for(int i = 1; i <= M; ++ i)	if(Flt[i].p <= P[p].cost && Flt[i].q <= Q[q].cost)
memset(vis, 0, sizeof vis );
Dfs(1);
for(int i = 1; i <= N; ++ i)	if(! vis[i])	return 0;
return 1;
}

int main(){
//freopen("meizi.in", "r", stdin);
//freopen("meizi.out", "w", stdout);
getint(N), getint(M);
for(int i = 1; i <= M; ++ i){
getint(Flt[i].u), getint(Flt[i].v), getint(Flt[i].p), getint(Flt[i].q);
P[i].cost = Flt[i].p, P[i].pos = i;
Q[i].cost = Flt[i].q, Q[i].pos = i;
}
sort(P + 1, P + 1 + M);
//int A = unique(P + 1, P + 1 + M) - P;
sort(Q + 1, Q + 1 + M);
//int B = unique(Q + 1, Q + 1 + M) - Q;
int p = M, q = 1, Ans = INF;
while(p){
for( ; q <= M; ++ q)	if(Check(p, q)){
Ans = min(Ans, P[p].cost + Q[q].cost);
break;
}
-- p;
}
printf("%d\n", Ans);
return 0;
}	

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

const int Maxn = 2000;
const int Maxm = 5000;
const int INF = 0x3f3f3f3f;

struct FF{
int cost, pos;
bool operator < (const FF & X) const{
return cost < X.cost;
}
}P[Maxm + 5], Q[Maxm + 5];
struct node{
int u, v, p, q;
bool operator < (const node & X) const{
return p + q < X.p + X.q;
}
}Flt[Maxm + 5];
struct E{
int v, nxt;
}edge[(Maxm << 1) + 5];

int N, M, cnt;
int fir[Maxn + 5];
bool vis[Maxn + 5];

bool getint(int & num){
char c;	int flg = 1;	num = 0;
while((c = getchar()) < '0' || c > '9'){
if(c == '-')	flg = -1;
if(c == -1)	return 0;
}
while(c >= '0' && c <= '9'){
num = num * 10 + c - 48;
if((c = getchar()) == -1)	return 0;
}
num *= flg;
return 1;
}

edge[++ cnt].v = b, edge[cnt].nxt = fir[a], fir[a] = cnt;
edge[++ cnt].v = a, edge[cnt].nxt = fir[b], fir[b] = cnt;
}

void Dfs(int x){
vis[x] = 1;
for(int i = fir[x]; i; i = edge[i].nxt)	if(! vis[edge[i].v])
Dfs(edge[i].v);
}

bool Check(int p, int q){
for( ; q <= M && Q[q].cost == Q[q + 1].cost; ++ q);
cnt = 0;
memset(fir, 0, sizeof fir );
int B = Q[q].cost;
for(int i = 1; i <= p; ++ i){
int tmp = P[i].pos;
if(Flt[tmp].q <= B)
}
memset(vis, 0, sizeof vis );
Dfs(1);
for(int i = 1; i <= N; ++ i)	if(! vis[i])	return 0;
return 1;
}

int Find(int p){
for(; p <= M && P[p].cost == P[p + 1].cost; ++ p);
int dn = max(N - 1 - p, 0), up = M, mid, rt = INF;
while(dn <= up){
mid = (dn + up) >> 1;
if(mid + p < N - 1)	dn = mid + 1;
else{
if(Check(p, mid))
rt = Q[mid].cost, up = mid - 1;
else dn = mid + 1;
}
}
if(rt != INF)	return rt;
else return 0x7f7f7f7f;
}

int Find1(int q){
for(; q <= M && Q[q].cost == Q[q + 1].cost; ++ q);
int dn = max(N - 1 - q, 0), up = M, mid, rt = INF;
while(dn <= up){
mid = (dn + up) >> 1;
if(mid + q < N - 1)	dn = mid + 1;
else{
if(Check(mid, q))
rt = P[mid].cost, up = mid - 1;
else dn = mid + 1;
}
}
if(rt != INF)	return rt;
else return 0x7f7f7f7f;
}

int main(){
//freopen("meizi.in", "r", stdin);
//freopen("meizi.out", "w", stdout);
getint(N), getint(M);
for(int i = 1; i <= M; ++ i){
getint(Flt[i].u), getint(Flt[i].v), getint(Flt[i].p), getint(Flt[i].q);
P[i].cost = Flt[i].p, P[i].pos = i;
Q[i].cost = Flt[i].q, Q[i].pos = i;
}
sort(P + 1, P + 1 + M);
sort(Q + 1, Q + 1 + M);
int dn = 1, up = M, mid, all = INF, b;
while(dn <= up){
mid = (dn + up) >> 1;
b = Find(mid);
if(P[mid].cost + b <= all)
all = P[mid].cost + b, up = mid - 1;
else dn = mid + 1;
}
int all2 = INF;
dn = 1, up = M;
while(dn <= up){
mid = (dn + up) >> 1;
b = Find1(mid);
if(Q[mid].cost + b <= all2)
all2 = Q[mid].cost + b, up = mid - 1;
else dn = mid + 1;
}
printf("%d\n", min(all, all2));
return 0;
}	

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客