「JOISC 2014 Day3」电压
Description
JOI 公司的某个实验室中有着复杂的电路。电路由 (N) 个节点和 (M) 根细长的电阻组成。节点编号为 (1sim N)。
每个节点可设定为两种电平之一:高电平或者低电平。每个电阻连接两个节点,只有一端是高电平,另一端是低电平的电阻才会有电流流过。两端都是高电平或者低电平的电阻不会有电流流过。
试求:有多少个电阻,可以通过调节各节点的电压,使得「没有电流流经该电阻,且其他 (M-1) 根电阻中都有电流流过」。
(Nle 10^5,Mle 2 imes 10^5)
Solution
不难看出,一条边满足条件的情况当且仅当奇环都包含这条边且偶环都不包含这条边。然后这个可以直接 dfs 树上差分。
时间复杂度 (Theta(n+m))。
Code
#include <bits/stdc++.h>
using namespace std;
#define Int register int
#define MAXN 100005
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> void read (T &x,Args& ... args){read (x),read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
int n,m;
struct edge{
int v,nxt;
}e[MAXN << 2];
int toop = 1,head[MAXN];
void Add_Edge (int u,int v){
e[++ toop] = edge {v,head[u]},head[u] = toop;
e[++ toop] = edge {u,head[v]},head[v] = toop;
}
bool rt[MAXN],vis[MAXN];
int ocnt,dep[MAXN],ores[MAXN],eres[MAXN];
void dfs (int u,int fa){
vis[u] = 1;
for (Int i = head[u];i;i = e[i].nxt) if (i ^ fa ^ 1){
int v = e[i].v;
if (!vis[v]) dep[v] = dep[u] + 1,dfs (v,i),ores[u] += ores[v],eres[u] += eres[v];
else if (dep[v] < dep[u]){
if (dep[u] - dep[v] & 1) eres[u] ++,eres[v] --;
else ores[u] ++,ores[v] --,ocnt ++;
}
}
}
signed main(){
read (n,m);
for (Int i = 1,u,v;i <= m;++ i) read (u,v),Add_Edge (u,v);
for (Int i = 1;i <= n;++ i) if (!vis[i]) rt[i] = 1,dfs (i,0);
int ans = ocnt == 1;for (Int i = 1;i <= n;++ i) if (!rt[i] && !eres[i] && ores[i] == ocnt) ans ++;
write (ans),putchar ('
');
return 0;
}
导弹防御塔
Solution
可以二分答案,然后把每一个防御塔拆开跑二分图匹配。
时间复杂度玄学。
Code
#include <bits/stdc++.h>
using namespace std;
#define Int register int
#define MAXN 55
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> void read (T &x,Args& ... args){read (x),read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
double t1,t2;
vector <int> G[MAXN * MAXN];
int n,m,tot,v,my[MAXN * MAXN];
struct node{
int id;double pret;
}ver[MAXN * MAXN];
void prepare (){
for (Int i = 1;i <= n;++ i)
for (Int j = 1;j <= m;++ j)
ver[++ tot] = node {i,(j - 1) * (t1 + t2) + t1};
}
int sqr (int x){return x * x;}
struct Point{
int x,y;
void getit (){read (x,y);}
friend double dist (Point a,Point b){return sqrt (sqr (a.x - b.x) + sqr (a.y - b.y));}
}dat[MAXN],ene[MAXN];
bool vis[MAXN * MAXN];
bool dfs (int u){
for (Int v : G[u]) if (!vis[v]){
vis[v] = 1;
if (my[v] == -1 || dfs (my[v])){
my[v] = u;
return 1;
}
}
return 0;
}
bool check (double s){
for (Int i = 1;i <= m;++ i) G[i].clear();
memset (my,-1,sizeof (my));
for (Int i = 1;i <= m;++ i)
for (Int j = 1;j <= tot;++ j)
if (ver[j].pret + dist (ene[i],dat[ver[j].id]) / v <= s)
G[i].push_back (j);
int ans = 0;
for (Int i = 1;i <= m;++ i) memset (vis,0,sizeof (vis)),ans += dfs (i);
return ans == m;
}
signed main(){
read (n,m),scanf ("%lf%lf",&t1,&t2),t1 /= 60,read (v);prepare ();
for (Int i = 1;i <= m;++ i) ene[i].getit();
for (Int i = 1;i <= n;++ i) dat[i].getit();
double l = 0,r = 1e9,ans = -1;
while (r - l > 1e-7){
double mid = (l + r) / 2;
if (check (mid)) ans = mid,r = mid;
else l = mid;
}
printf ("%.6f
",ans);
return 0;
}