题解
- 看到最大值最小,无脑二分先(不管有没有用)
- 考虑现将代价排序,然后二分一个代价mid,显然我们要使所有的代价都小于mid而且要可以选出两个使得所有运营商都可以打
- 然后我们先把代价都小于mid的都标记一下,将每个运营商的出度求出来(也就是能打到的最多运营商)
- 然后将其排序,那么这样的话,我们就能枚举两个运营商判断其能打的运营商是否等于n就好了
代码
1 #include <cstdio>
2 #include <iostream>
3 #include <bitset>
4 #include <cstring>
5 #include <algorithm>
6 #define N 10010
7 using namespace std;
8 bitset<N> Q[N],P;
9 struct edge{ int x,y,v; }e[N*10],a[N];
10 int n,m,k,p[N*10],l[N];
11 bool cmp(edge a,edge b) { return a.x<b.x; }
12 bool check(int x)
13 {
14 memset(l,0,sizeof(l));
15 for (int i=1;i<=n;i++) Q[i].reset();
16 for (int i=1;i<=k;i++) if (e[i].v<=x) l[e[i].x]++,Q[e[i].x][e[i].y]=1;
17 for (int i=1;i<=n;i++) a[i].x=l[i],a[i].y=i;
18 sort(a+1,a+n+1,cmp);
19 for (int i=n;i&&a[i].x*2>=n;i--)
20 for (int j=i-1;j&&a[i].x+a[j].x>=n;j--)
21 {
22 P=Q[a[i].y]|Q[a[j].y];
23 if (P.count()==n) return 1;
24 }
25 return 0;
26 }
27 int main()
28 {
29 scanf("%d%d",&n,&k);
30 for (int i=1;i<=k;i++) scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].v),p[i]=e[i].v;
31 sort(p+1,p+k+1); int l=1,r=k;
32 while (l<r-1)
33 {
34 int mid=l+r>>1;
35 if (check(p[mid])) r=mid; else l=mid+1;
36 }
37 if (check(p[l])) printf("%d",p[l]); else if (check(p[r])) printf("%d",p[r]); else printf("No solution");
38 }