[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) ...
随机推荐
- 【控制连接实现信息共享---linux和设备下ssh和远程连接telnet服务的简单搭建】
SSH的配置 空密码登陆ssh server 如果要登录ssh server通常要在server和client之间采取具有共同加密的秘钥,若每次当client想要了:连接ssh server时都要手工 ...
- 【坑】记录一个docker 1.13.1 build 07f3374 版本的坑
在自家的开发环境中,一般都是直接yum安装最新的docker来做镜像和容器,没有仔细深究,一直相安无事.但这几天却发现一个惊悚的现象,新申请的两台虚机,一台安装好后正常,另一台却出现异常: docke ...
- SHELL里执行HIVE导出文件处理成CSV文件
#!/bin/bash #用途: #.当前目录的txt文件批量转csv #.制表符转逗号分隔符 #.NULL去除 #.删除WARN警告 for i in `ls ./*.txt` do sed -e ...
- P1049 装箱问题
装箱问题 题目描述 有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30,每个物品有一个体积(正整数). 要求n个物品中,任取若干个装入箱内,使 ...
- java 获取图片大小(尺寸)
1,获取本地图片大小(尺寸) File picture=new File(strSrc);BufferedImage sourceImg=ImageIO.read(new FileInputStrea ...
- web框架与爬虫
所有的web框架 http://www.cnblogs.com/wupeiqi/articles/5341480.html 爬虫技术 http://www.cnblogs.com/wupeiqi/ar ...
- linux mysql root 忘记密码了,完美解决-费元星站长
修改MySQL的配置文件(默认为/etc/my.cnf),在[mysqld]下添加一行skip-grant-tables 保存配置文件后,重启MySQL服务 service mysqld rest ...
- Qt Qwdget 汽车仪表知识点拆解3 进度条编写
先贴上效果图,注意,没有写逻辑,都是乱动的 这篇我来说说左侧的这个进度条的实现原理,其实更简单,哈哈哈 有一个大的widget,根据素材,我放了10个label 剩下的就是写一个函数,根据数据的不同, ...
- 为什么mysqld启动报错
在一台ubuntu测试机器上启动一个mysql实例,本来应该是一件很简单的事情, 启动的时候却报错了: mysqld_safe --defaults-file=/etc/mysql/my3307. ...
- Visual Studio 2010安装包
点击下载