第一次做二分图染色qwq,用了一个下午qwq,看电脑看的我眼睛难受
这个题满足二分的性质,因此二分图+二分……
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<vector> #include<queue> using namespace std; struct in { int to,ne,co; }ter[200020]; queue<int>qwq; bool flag; int n,m,t,x,l,r,y,z,tail,head[200020],col[20005],a[100005]; inline void build(int f,int l,int c) { ter[++tail]=(in){l,head[f],c},head[f]=tail; ter[++tail]=(in){f,head[l],c},head[l]=tail; } inline void bfs(int xx,int qi) { if(!flag)//如果之前发现当前答案不能满足则直接返回 return; while(!qwq.empty()) qwq.pop(); qwq.push(qi); col[qi]=1; while(!qwq.empty()) { int qaq=qwq.front(); for(int i=head[qaq];i;i=ter[i].ne) { if(ter[i].co<=xx)//如果说这对犯人的怒气值小于当前答案,则说明他们可以被接受 continue; if(col[ter[i].to]>0)//如果现在找到的点之前被走过 { if(col[ter[i].to]==col[qaq])//且颜色与现在的队首颜色相同 { flag=0;return;//当前答案不成立,返回 } } else//否则染色 col[ter[i].to]=3-col[qaq],qwq.push(ter[i].to); } qwq.pop(); } } inline bool ask(int xia) { int biao=a[xia]; memset(col,-1,sizeof(col)); flag=1; for(int i=1;i<=n;i++) if(col[i]<0)//如果这个点没有走过 bfs(biao,i); return flag; } int main() { scanf("%d%d",&n,&m); memset(head,-1,sizeof(head)); for(int i=1;i<=m;i++) scanf("%d%d%d",&x,&y,&z),build(x,y,z),a[i+1]=z; a[1]=0; sort(a+1,a+2+m);//先排个序,便于下面二分 l=1,r=m+1;//l,r是数组下标 while(l<r)//二分答案 { int mid=l+r>>1; if(ask(mid))//如果返回值为真,则说明现在的答案太大,可以进一步缩小 r=mid; else//否则说明答案太小 l=mid+1; } printf("%d",a[l]); }