题意:给出一个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. Javascript的执行过程详细研究

    下面我们以更形象的示例来说明JavaScript代码在页面中的执行顺序.如果说,JavaScript引擎的工作机制比较深奥是因为它属于底层行为,那么JavaScript代码执行顺序就比较形象了,因为我 ...

  2. Map总结

    Map是键值对集合,是一对一对往上存的,要保持键的唯一性 形式:Map<K, V> 方法: 增 put(K key, V value) 若存储时Map中有相同的键,则返回原来键的值,并覆盖 ...

  3. python 版本zabbix_sender

    python版本的zabbix_sender: 使用方法:    1.导入 : from zbx_send import info        2.实例化: test=info()     3.支持 ...

  4. Go Web 编程 第一章 Web相关概念

    第一章 Go与Web应用 Go学习群:415660935 1.1 Web应用 在计算机的世界里,应用(application)是一个与用户进行交互,并完成用户特定任务的软件程序.而Web应用则是部署在 ...

  5. 福建工程学院寒假作业第三周B题

    第二集 你说,你的女朋友就是你的电脑 TimeLimit:2000ms  MemoryLimit:128000KB 64-bit integer IO format:%lld   Problem De ...

  6. vsts 自动部署到Azure

    如果要部署到中国区的Azure ,请先阅读 http://www.cnblogs.com/cnryb/p/7867275.html 前置条件,我把代码托管在vsts(放在GitHub上也没问题,这里不 ...

  7. count(*)与count(1)、count('xxx')等在使用语法方面的区别

    语法方面: 区别就是:没有区别!!! “*”号是通配符: “*”号是通配符 “*”号是通配符 使用"*"号和使用其他数字和任意非字段字符在使用方面没有任何语法错误; 至于效率方面是 ...

  8. python redis-string、list、set操作

    string操作 redis中的string在内存中都是按照一个key对应一个value来存储的 方法: set() 方法 : 写入一条数据 mset() 方法: 写入多条数据 , 可是Key-Val ...

  9. Python+Selenium 自动化实现实例-实现文件下载

    #coding=utf-8 from selenium import webdriver #实例化一个火狐配置文件 fp = webdriver.FirefoxProfile() #设置各项参数,参数 ...

  10. C++如何取得int型的最大最小值

    转:http://www.cnblogs.com/alex4814/archive/2011/09/12/2174173.html 當題目涉及到求最大最小值時,最初的比較數字就應當設置爲INT_MAX ...