题意:给出一个n个点m条边的有向无环图(DAG),初始的时候所有的点都为白色。然后有Q次操作,每次操作要把一个点的颜色改变,白色<->黑色,对于每次操作,输出满足下列点对<u,v>,u,v都为白色且可以相互到达的个数。

数据范围:

DAG上的问题,首先最暴力的方法就是,对于每一次更改都进行一遍dfs,B[u][v],表示U点可以到达v点,然后对于U的父亲结点来说,暴力合并,复杂度约为n^4,这样显然会爆炸。解法是每次用BITSET优化,因为B[u][v]的状态非零即一。

代码如下:

#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int maxn = 350;
int N, M, Q;
struct Edge
{
int to, next;
Edge(int to = 0, int next = 0): to(to), next(next) {}
} E[maxn * maxn];
int head[maxn], tot;
void initedge()
{
memset(head, -1, sizeof(head));
tot = 0;
}
void addedge(int u, int v)
{
E[tot] = Edge(v, head[u]);
head[u] = tot++;
}
bitset<maxn>BT[maxn];
int vis[maxn], cul[maxn];
void init()
{
for(int i = 0; i <= N; i++)
{
BT[i].reset();
vis[i] = cul[i] = 0;
}
}
void DFS(int u)
{
BT[u].reset();
BT[u][u] = 1;
vis[u] = 1;
if(cul[u]) return ;
for(int k = head[u]; ~k; k = E[k].next)
{
int v = E[k].to;
if(!vis[v]) DFS(v);
if(!cul[v]) BT[u] |= BT[v];
}
}
int main ()
{
while(~scanf("%d %d %d", &N, &M, &Q))
{
init();
initedge();
for(int i = 1; i <= M; i++)
{
int u, v;
scanf("%d %d", &u, &v);
addedge(u, v);
}
for(int i = 1; i <= Q; i++)
{
int u, ans = 0;
scanf("%d", &u);
cul[u] ^= 1;
for(int i = 1; i <= N; i++) vis[i] = 0;
for(int i = 1; i <= N; i++)
{
if(!vis[i]) DFS(i);
ans += BT[i].count() - 1;
}
printf("%d\n", ans);
}
}
return 0;
}

另外还有一种方法:

维护F[u][v],表示u->v的路径条数,然后对于每次操作更新F[u][v]-+=F[u][x]*F[x][v],然后判断F[u][v]是否>0即可,这样做是对的,但是F[u][v]可能非常大,要用unsigned long long ,虽然unsigned long long 存不下,但是他有自动取模的功能,即使是这样也有可能出现F[u][v]之间有路径,但是取模后为0的情况,但是这个概率是很小的,unsigned long long 已经很大了,取模后出现零的情况应该不会被卡。unsigned int 也可以过。

代码如下:

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long LL;
const int maxn = 350;
LL dp[maxn][maxn], vis[maxn];
int N, M, Q;
void init()
{
for(int i = 1; i <= N; i++)
{
vis[i] = 0;
for(int j = 1; j <= N; j++)
dp[i][j] = 0;
}
}
int main ()
{
while(~scanf("%d %d %d", &N, &M, &Q))
{
init();
for(int i = 1; i <= M; i++)
{
int u, v;
scanf("%d %d", &u, &v);
dp[u][v]++;
}
for(int k = 1; k <= N; k++ )
for(int st = 1; st < k; st++)
for(int ed = k + 1; ed <= N; ed++)
dp[st][ed] += dp[st][k] * dp[k][ed];
for(int i = 1; i <= Q; i++)
{
int u;
scanf("%d", &u);
if(vis[u] == 0)
{
vis[u] = 1;
for(int st = 1; st < u; st++)
for(int ed = u + 1; ed <= N; ed++)
dp[st][ed] -= dp[st][u] * dp[u][ed];
}
else
{
vis[u] = 0;
for(int st = 1; st < u; st++)
for(int ed = u + 1; ed <= N; ed++)
dp[st][ed] += dp[st][u] * dp[u][ed];
}
int ans = 0;
for(int st = 1; st <= N; st++)
{
if(vis[st]) continue;
for(int ed = st + 1; ed <= N; ed++)
{
if(vis[ed]) continue;
if(dp[st][ed] > 0) ans++;
}
}
printf("%d\n", ans);
}
}
return 0;
}

  

2017四川省赛D题《Dynamic Graph》的更多相关文章

  1. 2017四川省赛E题( Longest Increasing Subsequence)

    提交地址: https://www.icpc-camp.org/contests/4rgOTH2MbOau7Z 题意: 给出一个整数数组,F[i]定义为以i结尾的最长上升子序列,然后问以此删除掉第i个 ...

  2. 【数论】【原根】【动态规划】【bitset】2017四川省赛 K.2017 Revenge

    题意: 给你n(不超过200w)个数,和一个数r,问你有多少种方案,使得你取出某个子集,能够让它们的乘积 mod 2017等于r. 2017有5这个原根,可以使用离散对数(指标)的思想把乘法转化成加法 ...

  3. 2017湘潭赛 A题 Determinant (高斯消元取模)

    链接 http://202.197.224.59/OnlineJudge2/index.php/Problem/read/id/1260 今年湘潭的A题 题意不难 大意是把n*(n+1)矩阵去掉某一列 ...

  4. ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛 i题 Minimum(线段树)

    描述 You are given a list of integers a0, a1, …, a2^k-1. You need to support two types of queries: 1. ...

  5. XTU 1267 - Highway - [树的直径][2017湘潭邀请赛H题(江苏省赛)]

    这道题可能有毒……总之一会儿能过一会儿不能过的,搞的我很心烦…… 依然是上次2017江苏省赛的题目,之前期末考试结束了之后有想补一下这道题,当时比较懵逼不知道怎么做……看了题解也不是很懂……就只好放弃 ...

  6. XTU 1260 - Determinant - [2017湘潭邀请赛A题(江苏省赛)][高斯消元法][快速幂和逆元]

    是2017江苏省赛的第一题,当时在场上没做出来(废话,那个时候又不懂高斯消元怎么写……而且数论也学得一塌糊涂,现在回来补了) 省赛结束之后,题解pdf就出来了,一看题解,嗯……加一行再求逆矩阵从而得到 ...

  7. XTU 1264 - Partial Sum - [2017湘潭邀请赛E题(江苏省赛)]

    2017江苏省赛的E题,当时在场上看错了题目没做出来,现在补一下…… 题目链接:http://202.197.224.59/OnlineJudge2/index.php/Problem/read/id ...

  8. 2017年第六届数学中国数学建模国际赛(小美赛)C题解题思路

    这篇文章主要是介绍下C题的解题思路,首先我们对这道C题进行一个整体的概括,结构如下: C题:经济类 第一问:发现危险人群. 发现:欺诈的方式开始.雇佣或浪漫的承诺. 数据→确定特定的经济萧条地区→确定 ...

  9. 论文笔记:(TOG2019)DGCNN : Dynamic Graph CNN for Learning on Point Clouds

    目录 摘要 一.引言 二.相关工作 三.我们的方法 3.1 边缘卷积Edge Convolution 3.2动态图更新 3.3 性质 3.4 与现有方法比较 四.评估 4.1 分类 4.2 模型复杂度 ...

随机推荐

  1. .NET面试题系列(一)基本概念

    什么是CLR CLR常用简写词语,CLR是公共语言运行库(Common Language Runtime)和Java虚拟机一样也是一个运行时环境,它负责资源管理(内存分配和垃圾收集等),并保证应用和底 ...

  2. iOS数据存取---iOS-Apple苹果官方文档翻译

    CHENYILONG Blog iOS数据存取---iOS-Apple苹果官方文档翻译 数据存取/*技术博客http://www.cnblogs.com/ChenYilong/ 新浪微博http:// ...

  3. 【leetcode 简单】第十四题 最后一个单词的长度

    给定一个仅包含大小写字母和空格 ' ' 的字符串,返回其最后一个单词的长度. 如果不存在最后一个单词,请返回 0 . 说明:一个单词是指由字母组成,但不包含任何空格的字符串. 示例: 输入: &quo ...

  4. Feather包实现数据框快速读写,你值得拥有

    什么是Feather? Feature是一种文件格式,支持R语言和Python的交互式存储,速度更快.目前支持R语言的data.frame和Python pandas 的DataFrame. Feat ...

  5. Ubuntu 14.04 64位上安装wps office软件(转http://m.blog.csdn.net/blog/yhc13429826359/24179933)

    废话少说,只给出方法供各位参考!wps for Linux版本已经有两三年没有大的动作,当然其他平台,比如windows,Android,ios上的wps效果还是很赞的说. 下面是我成功安装的步骤: ...

  6. javascript反混淆之packed混淆(一)

    javascript反混淆之packed混淆(一) 什么是JavaScript反混淆,在理解这个概念前我们先来看下什么是代码混淆,代码混淆,是将计算机程序的代码,转换成一种功能上等价,但是难于阅读和理 ...

  7. 017 CPU冲高定位方法

    1.通过top命令查看cpu占用高的进程ID; 2.通过top -Hp 进程ID 查看该进程下所有线程占用cpu的情况,拿出占用cpu最高的线程ID,换算成十六进制; 3.通过 jstack 进程ID ...

  8. 9.Python3标准库--数据压缩与归档

    ''' 尽管现代计算机系统的存储能力日益增长,但生成数据的增长是永无休止的. 无损(lossless)压缩算法以压缩或解压缩数据花费的时间来换取存储数据所需要的空间,以弥补存储能力的不足. Pytho ...

  9. Debian系网络配置 /etc/network/interfaces

    说Debian系的网卡配置跟Redhat系很不一样,Redhat是放在/etc/sysconfig/network-scripts目录下面的一大堆文件里面,要修改?你一个一个文件来过吧.Debian系 ...

  10. C语言 五子棋2

    #include<windows.h> #include<stdlib.h> #include<stdio.h> #include<conio.h> # ...