社区讨论

30 分代码玄关求条 AC on #1#2#3

P4926[1007] 倍杀测量者参与者 2已保存回复 2

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
2 条
当前快照
1 份
快照标识符
@m5w6ozu2
此快照首次捕获于
2025/01/14 16:01
去年
此快照最后确认于
2025/11/04 11:37
4 个月前
查看原帖
我对着题解看了好久没看出问题,看了警示后人也不知道是哪里错了。
代码如下:
CPP
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define lowbit(x) (x&-x)
#define pii pair<int,int>
#define N 2010
#define M 16010
#define eps 1e-6
namespace graph{
    int head[N],nxt[M],to[M];
    double weig[M];// 边权(小数)
    int cnt_edge;
    inline void connect_head(const int &x,const int &y,const double &w){
        ++cnt_edge;
        nxt[cnt_edge] = head[x];
        to[cnt_edge] = y;
        weig[cnt_edge] = w;
        head[x] = cnt_edge;
    }
}
using namespace graph;
int n,s,t,tmp;
struct edge{
    int op,a,b;
    double k;
}p[M];
double l,r,mid,nx;
bool inq[N];// 在队列中
int cnt[N];
double d[N];
bool ud[N];
double dst[N];// 跑最长路判断是否可行


inline void push(){
    memset(head,0,(n<<2)+40);
    cnt_edge = 0;
    // 根据条件放入边
    for(int i = 1;i <= s;++i){
        if(p[i].op == 1){
            connect_head(p[i].b,p[i].a,log2(p[i].k - mid));
        }else{
            connect_head(p[i].b,p[i].a,-log2(p[i].k + mid));
        }
    }
    // 根据一些限制放入边
    dst[0] = -INF,cnt[0] = inq[0] = 0;
    for(int i = 1;i <= n;++i){
        dst[i] = -INF;
        cnt[i] = inq[i] = 0;
        if(!ud[i])continue;
        connect_head(0,i,d[i]);
        connect_head(i,0,-d[i]);
    }
    for(int i = 0;i <= n;++i)connect_head(n+1,i,0);
    dst[n+1] = 0,cnt[n+1] = inq[n+1] = 0;
}

inline bool check(){
    // 放入
    push();
    // spfa 最长路
    queue<int> q;
    q.push(n+1);
    int x;
    while(q.size()){
        x = q.front();
        q.pop();
        inq[x] = 0;
        // printf("spfa %d\n",x);
        for(int edg = head[x];edg;edg = nxt[edg]){
            nx = dst[x] + weig[edg];
            if(abs(dst[to[edg]] - nx) <= eps || dst[to[edg]] > nx)continue;
            dst[to[edg]] = nx;
            if(inq[to[edg]])continue;
            inq[to[edg]] = 1;
            ++cnt[to[edg]];
            q.push(to[edg]);
            if(cnt[to[edg]] > n + 1)return 0;// 不可行,有人要女装
        }
    }
    return 1;
}

// 输入函数
void input(){
    scanf("%d%d%d",&n,&s,&t);
    r = 10;
    for(int i = 1;i <= s;++i){
        scanf("%d%d%d%lf",&p[i].op,&p[i].a,&p[i].b,&p[i].k);
        r = min(r,p[i].k);
    }
    // 输入 t 个已知选手
    for(int i = 1;i <= t;++i){
        scanf("%d",&tmp);
        scanf("%lf",d+tmp);
        ud[tmp] = 1;
        d[tmp] = log2(d[tmp]);
    }
}

// 处理函数
void solve(){
    mid = 0;
    if(check()){
        r = 0;
        return;
    }
    l = 0;
    // int cnt = 60;
    while(abs(r - l) > eps){
        mid = (l+r)/2;
        if(check())r = mid;
        else l = mid;
        // printf("mid = %.10lf\n",mid);
        // 输出 dst
        // for(int i = 0;i <= n;++i)printf("idx = %d dst = %.10lf\n",i,dst[i]);
    }
}

// 输出函数
void output(){
    mid = (l+r)/2;
    if(check())printf("-1");
    else printf("%.10lf",mid);
}

// 主函数
int main(){
    input();
    solve();
    output();
    return 0;
}

回复

2 条回复,欢迎继续交流。

正在加载回复...