题解 P4079 【[SDOI2016]齿轮】
做题需要一点暴力的勇气......
一看n只有这么点大,我就把什么并查集什么逆元忽略了,直接染色加宽搜走一波
然而打下来只有70分,错的还是前三个点......我抓破脑袋想不出来哪儿错了,召唤前排神犇LRL52搞了一会儿也没什么结果......于是果断去隔壁loj.ac搞了数据来debug,最后发现还是我和LRL52都坚信不会错的重链判断上凉了......
所以果然......越自信越容易出事儿骄傲自满必翻车by陈毅
不废话了,上代码
#include<bits/stdc++.h>
using namespace std;
std::vector<int>G[1005];
std::vector<double>W[1005];
int N,M,vis[1005];
double eps=1e-5,cnt[1005];//eps不能太小
struct node{
int id;//这是id号齿轮
double circle;//它现在转了circle圈
};
bool BFS(){
for(int i=1;i<=N;i++){
if(vis[i])continue;//这个vis其实有点像一个并查集(其实就是染色),可以保证对于一个集合只搜索一次(这个组可能划分成多个毫不相关的集合嘛)
node c;
c.circle=cnt[i]=1;
c.id=i;
vis[i]=1;//初始化
queue<node>Q;
Q.push(c);
while(!Q.empty()){
node u=Q.front();
Q.pop();
for(int i=0;i<G[u.id].size();i++){
int v=G[u.id][i];
double cc=u.circle*W[u.id][i];//注意一下W[i][j]的第二维,想一想为什么不直接用v
if(!vis[v]){
vis[v]=1;
cnt[v]=cc;
Q.push(node{v,cc});
}
else if(fabs(cc-cnt[v])>eps)return false;//入过队列了就只判断符合条件与否了,再入队的话就没完没了了(@李溢出)
}
}
}
return true;//如果都没问题就true了呗
}
int main(){
//freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
for(int kkk=1;kkk<=T;kkk++){//不要在意细节
memset(vis,0,sizeof(vis));
memset(W,0,sizeof(W));
memset(cnt,0,sizeof(cnt));
scanf("%d%d",&N,&M);
for(int i=1;i<=N;i++)
G[i].clear();
for(int i=1,u,v,x,y;i<=M;i++){
scanf("%d%d%d%d",&u,&v,&x,&y);
G[u].push_back(v);
G[v].push_back(u);
W[u].push_back((double)y/x);//这里要保证比例是一条一条链对应过去的,否则以两个齿轮的id保存的话会使不同的链用同一个比例
W[v].push_back((double)x/y);//双向边是要建的
}
if(BFS())printf("Case #%d: Yes\n",kkk);
else printf("Case #%d: No\n",kkk);
}
return 0;
}
于是就完事儿了。我去看LXL翻车了(hiahiahia)。