[CF475E]Strongly Connected City 2
题目大意:给一张$n(n\leqslant2000)$个点的无向图,给所有边定向,使定向之后存在最多的有序点对$(a,b)$满足从$a$能到$b$
题解:先把边双缩点,因为这里面的点一定两两可达。
根据网上题解得知,最优解一定长这样:存在一个点$s$,使得对于任意其他点$t$,要么$s$可以到$t$,要么$t$可以到$s$,就把$s$作为根。(出题人的题解也没给出解答,就感性理解)
所以$s$的每一个子树内的边要么都朝向$s$,要么都远离$s$
然后可以枚举哪个点作为根,记$w_i$第$i$个双联通分量的大小,$sz_i$为以第$i$个双联通分量为根的子树大小,每个子树内的点在子树内的贡献为$w_i(sz_i-w_i)$,令$P$为朝向根的节点的$sz$和,过根的贡献为$P(n-w_s-P)$,所以只需要让$P$与$(n-w_s-P)$尽可能接近即可,可以用背包来实现
卡点:无
C++ Code:
#include <cstdio>
#include <bitset>
#define maxn 2010
#define maxm (maxn * maxn)
inline int min(int a, int b) {return a < b ? a : b;}
inline int max(int a, int b) {return a > b ? a : b;} int n, m; namespace Graph {
int head[maxn], cnt = 1;
struct Edge {
int to, nxt;
} e[maxm];
inline void addE(int a, int b) {
e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;
e[++cnt] = (Edge) {a, head[b]}; head[b] = cnt;
} int w[maxn];
int DFN[maxn], low[maxn], idx;
int S[maxn], top, res[maxn], scc;
void tarjan(int u, int fa = 0) {
DFN[u] = low[u] = ++idx;
S[++top] = u;
int v;
for (int i = head[u]; i; i = e[i].nxt) {
v = e[i].to;
if (v != fa) {
if (!DFN[v]) {
tarjan(v, u);
low[u] = min(low[u], low[v]);
} else low[u] = min(low[u], DFN[v]);
}
}
if (DFN[u] == low[u]) {
scc++;
do {
v = S[top--];
w[res[v] = scc]++;
} while (u != v);
}
}
} long long ans;
namespace Tree {
int head[maxn], cnt;
struct Edge {
int to, nxt;
} e[maxn << 1];
inline void addE(int a, int b) {
e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;
e[++cnt] = (Edge) {a, head[b]}; head[b] = cnt;
}
using Graph::res;
using Graph::w;
using Graph::scc; void init(int n, int m) {
for (int i = 1; i <= n; i++) if (!Graph::DFN[i]) Graph::tarjan(i);
for (int i = 2; i <= Graph::cnt; i += 2) {
int u = Graph::e[i ^ 1].to, v = Graph::e[i].to;
if (res[u] != res[v]) addE(res[u], res[v]);
}
} int sz[maxn];
int __ans, sumsz;
std::bitset<maxn / 2> B;
#define ans __ans
void dfs(int u, int fa = 0) {
sz[u] = w[u];
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (v != fa) {
dfs(v, u);
sz[u] += sz[v];
}
}
ans += sz[u] * w[u];
}
int calc(int u) {
B.reset();
B[0] = true;
ans = 0; dfs(u);
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
B |= B << sz[v];
}
for (int i = sumsz - w[u] >> 1; i; i--) if (B[i]) return ans + i * (sumsz - w[u] - i);
return ans;
}
#undef ans int q[maxn], h, t;
bool vis[maxn];
void solve(int u) {
vis[q[h = t = 0] = u] = true;
int res = 0;
sumsz = 0;
while (h <= t) {
int u = q[h++];
sumsz += w[u];
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (!vis[v]) vis[q[++t] = v] = true;
}
}
for (int i = 0; i <= t; i++) res = max(res, calc(q[i]));
ans += res;
}
void work() {
for (int i = 1; i <= scc; i++) if (!vis[i]) solve(i);
}
} int main() {
scanf("%d%d", &n, &m);
for (int i = 0, a, b; i < m; i++) {
scanf("%d%d", &a, &b);
Graph::addE(a, b);
}
Tree::init(n, m);
Tree::work();
printf("%lld\n", ans);
return 0;
}
[CF475E]Strongly Connected City 2的更多相关文章
- cf475B Strongly Connected City
B. Strongly Connected City time limit per test 2 seconds memory limit per test 256 megabytes input s ...
- codeforces B. Strongly Connected City(dfs水过)
题意:有横向和纵向的街道,每个街道只有一个方向,垂直的街道相交会产生一个节点,这样每个节点都有两个方向, 问是否每一个节点都可以由其他的节点到达.... 思路:规律没有想到,直接爆搜!每一个节点dfs ...
- Codeforces 475 B Strongly Connected City【DFS】
题意:给出n行m列的十字路口,<代表从东向西,>从西向东,v从北向南,^从南向北,问在任意一个十字路口是否都能走到其他任意的十字路口 四个方向搜,搜完之后,判断每个点能够访问的点的数目是否 ...
- Codeforces-475B Strongly Connected City
仅仅用推断最外层是不是回路 假设是 则每两个点之间连通 #include<iostream> #include<algorithm> #include<cstdio ...
- PTA Strongly Connected Components
Write a program to find the strongly connected components in a digraph. Format of functions: void St ...
- algorithm@ Strongly Connected Component
Strongly Connected Components A directed graph is strongly connected if there is a path between all ...
- Strongly connected(hdu4635(强连通分量))
/* http://acm.hdu.edu.cn/showproblem.php?pid=4635 Strongly connected Time Limit: 2000/1000 MS (Java/ ...
- 【CF913F】Strongly Connected Tournament 概率神题
[CF913F]Strongly Connected Tournament 题意:有n个人进行如下锦标赛: 1.所有人都和所有其他的人进行一场比赛,其中标号为i的人打赢标号为j的人(i<j)的概 ...
- HDU 4635 Strongly connected (Tarjan+一点数学分析)
Strongly connected Time Limit : 2000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other) ...
随机推荐
- filter-policy和AS-PATH-FILTER过滤BGP路由条目
Filter-policy过滤BGP路由条目 一:根据项目需求搭建好拓扑图如下: 二:配置 1:对项目图做理论分析,首先RT1和RT2属于EBGP(不同自治系统之间的直连路由),而RT2和RT3属于I ...
- hash和history的区别
vue-router 中hash模式和history模式. 在vue的路由配置中有mode选项,最直观的区别就是在url中hash 带了一个很丑的 # ,而history是没有#的.vue默认使用ha ...
- Java 使用Apache POI读取和写入Excel表格
1,引入所用的包 <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxm ...
- Flask之endpoint错误View function mapping is overwriting an existing endpoint function: ***
最近在学习Flask, 其中遇到了一个错误, 发现这个问题和Flask, 路由有关系, 所以就记了下来 错误代码: from flask import Flask, render_template, ...
- Hadoop(3)-Hadoop介绍
Hadoop三大发行版本 Hadoop三大发行版本:Apache.Cloudera.Hortonworks. Apache版本最原始(最基础)的版本,对于入门学习最好. Cloudera在大型互联网企 ...
- 使用Jcrop-canvas画布-制作前端图像裁剪
写在前面 –公司有这个需求,安排调查 –目前各大网站都是采用的-前端做裁剪返回坐标-由后端来做到裁剪 –而使用html-canvas画布可以直接前端裁剪并返回base64流-ajax可以直接下载保存 ...
- Redis缓存数据库的安装与配置(3)
3 Redis主动同步设置方法 Redis主从同步 1.Redis主从同步特点 一个master可以拥有多个slave 多个slave可以连接同一个master,还可以连接到其他slave 主从复制不 ...
- C语言实例解析精粹学习笔记——35(报数游戏)
实例35: 设由n个人站成一圈,分别被编号1,2,3,4,……,n.第一个人从1开始报数,每报数位m的人被从圈中推测,其后的人再次从1开始报数,重复上述过程,直至所有人都从圈中退出. 实例解析: 用链 ...
- C#中利用iTextSharp开发二维码防伪标签(1)
开发的基本说明与尝试 一个亲戚朋友是做防伪码印刷的,之前的电话防伪.短信防伪都用Delphi给他设计,使用也挺不错,后来又加了一个基于asp的网页版防伪查询.由于业务需求,今年年初朋友又提成希望能够完 ...
- Apache 配置说明
ServerRoot ServerRoot: The top of the directory tree under which the server's configuration, error, ...