头像

17865429953




离线:45分钟前


最近来访(31)
用户头像
毕莹
用户头像
ae
用户头像
小小灰
用户头像
蘑菇QQ糖
用户头像
小小志
用户头像
AC_440
用户头像
叶子.
用户头像
zzsxyacm01
用户头像
凯_8
用户头像
czpxlm
用户头像
杨大虾
用户头像
NashCSK
用户头像
zqc.AC
用户头像
德布罗意の猫
用户头像
Donot
用户头像
UyAey
用户头像
Distinctive
用户头像
dingabc
用户头像
三尺有明
用户头像
border-radius50


AcWing《Web应用课》拼团优惠!https://www.acwing.com/activity/content/introduction/1150/group_buy/134642/



新鲜事 原文

AcWing《Web应用课》拼团优惠!https://www.acwing.com/activity/content/introduction/1150/group_buy/134642/



AcWing《SpringBoot框架课》拼团优惠!https://www.acwing.com/activity/content/introduction/1877/group_buy/133496/



新鲜事 原文

AcWing《SpringBoot框架课》拼团优惠!https://www.acwing.com/activity/content/introduction/1877/group_buy/133496/



17865429953
6个月前
//两个点的集合编号是重合的,要给右半部分点的编号 统一加 n1 
#include<iostream>
#include<cstring>
using namespace std;
const int MAXM = 1e5 + 10, MAXN = 2 * 510;
int h[MAXM], e[MAXM], ne[MAXM], idx;
int n1, n2, m;
//st[]  在一次find(boy1) 中 产生了冲突 (即boy1看上的girl1已经和boy2匹配了)要让boy2再尝试find(boy2) 
//在find(boy2)过程中 就不能再去考虑girl1 所以要在find(boy2)之前标记一下st[girl1] = true;  
bool st[MAXN];//判重 不要重复搜一个点 
int match[MAXN];//记录右半部分和哪个左半部分的点匹配  match[girl] = boy

void add(int a, int b)
{
    e[idx] = b;
    ne[idx] = h[a];
    h[a] = idx;
    idx++;
}

bool find(int boy)
{
    for(int i = h[boy];i != -1;i = ne[i])
    {
        int girl = e[i];
        if(!st[girl])
        {
            st[girl] = true;
            if(!match[girl] || find(match[girl])) //如果nv 没有和别的点匹配 或者 match[nv] 可以换成别的点 
            {

                match[girl] = boy;
                return true;
            }
        }
    }
    return false;
}
int main()
{
    memset(h, -1, sizeof h);
    cin >> n1 >> n2 >> m;
    for(int i = 0;i < m;i++)
    {
        int a, b;
        cin >> a >> b;
        add(a, b+n1); //只需要存左边到右边的边即可  右边的点加n1 
    }
    int ans = 0;//匹配成功的数量 
    for(int i = 1;i <= n1;i++) //遍历左半部分的点 
    {
        memset(st, false, sizeof st);
        if(find(i))//第i个点 找右半部分的点匹配 
        ans++;
    }
    cout << ans; 
    return 0;
}



17865429953
6个月前
//二分图就是可以将点划分到两个集合 使得所有的边都连接两个集合的点 即 集合内部没有边 边在集合之间 
//一个图是二分图当且仅当途中不含奇数环(环中边的数量是奇数 也即环中的点也是奇数) 

#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 2e5 + 10;
int h[MAXN], e[MAXN], ne[MAXN], idx;
int n, m, color[MAXN];

void add(int a, int b)
{
    e[idx] = b;
    ne[idx] = h[a];
    h[a] = idx;
    idx++;
}

bool dfs(int v, int c)
{
    color[v] = c;
    for(int i = h[v];i != -1;i = ne[i])
    {
        int nv = e[i];
        if(!color[nv]) //如果没有染色就染色 
        {
            //要染成和c不一样的颜色 3-c 
            if(!dfs(nv, 3 - c)) return false;
        }
        else//如果该点染上了颜色  就判断是否有矛盾 v和nv是否是同一种颜色 
        {
            if(color[nv] == c)
            {
                return false; //有矛盾 
            } 
        }
    }
    return true;
}

int main()
{
    memset(h, -1, sizeof h);
    cin >> n >> m;
    for(int i = 0;i < m;i++)
    {
        int a, b;
        cin >> a >> b;
        add(a, b);
        add(b, a);
    }
    bool flag = true;
    for(int i = 1;i <= n;i++)
    {
        if(!color[i])
        {
            if(!dfs(i, 1)) //1代表一种颜色,2代表另一种颜色 
            {
                flag = false;
                break;
            }
        }
    }
    if(flag)
    cout << "Yes";
    else
    cout << "No";
    return 0;
} 



17865429953
6个月前
//y总 这里为什么一定重载小于号呢,是因为sort排序用的运算符是小于吗,我把重载改成大于 就报错了
//对滴,sort中用的都是小于号。
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 2 * 1e5 + 10;
struct Edge{
    int a;
    int b;
    int c;
} edge[MAXN];
int n, m;
int p[MAXN];
//如果cmp返回结果为假, 那么函数就会将他们互换位置;

//如果cmp返回结果为真,就会保持原来位置不变。
bool cmp(struct Edge& e1, struct Edge& e2)
{
    return e1.c < e2.c;
}

int find(int a)
{
    if(p[a] != a)
    {
        p[a] = find(p[a]);
    }
    return p[a];
}
int kruskal()
{
    sort(edge, edge+m,cmp);
    for(int i = 0;i <= n;i++)
    p[i] = i;
    int cnt = 0;//记录加入最小生成树中边的数量 
    int sum = 0;
    for(int i = 0;i < m;i++)//按边的权重从小到大遍历边 
    {
        int a = edge[i].a, b = edge[i].b, c = edge[i].c;
        int pa = find(a), pb = find(b);
        //如果边的两个端点不在同一个连通块 那就合并这两个连通块  并将这条边加入最小生成树中 
        if(pa != pb)
        {
            p[pa] = pb;
            sum += c;
            cnt++;
        }
    }
    if(cnt == n-1) //最小生成树有n-1条边。 
    return sum;
    else
    return -1; 
}
int main()
{
    cin >> n >> m;
    for(int i = 0;i < m;i++)
    {
        cin >> edge[i].a >> edge[i].b >> edge[i].c;
    }
    int ans = kruskal();
    if(ans == -1)
    cout << "impossible";
    else
    cout << ans;
    return 0;
}



17865429953
6个月前
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 510, inf = 0x3f3f3f3f;
int g[MAXN][MAXN], dist[MAXN];
int n, m;
bool st[MAXN];
int prim()
{
    memset(dist, inf, sizeof dist);
    dist[1] = 0;
    int sum = 0;
    for(int i = 0;i < n;i++)
    {
        int v = -1;
        for(int j = 1;j <= n;j++)
        {
            if(!st[j] && (v == -1 || dist[j] < dist[v]))
            v = j;
        }
        if(dist[v] == inf)
        return inf;
        st[v] = true;
        sum += dist[v]; 
        for(int j = 1;j <= n;j++)
        {
            if(!st[j] && g[v][j] != inf && dist[j] > g[v][j])
            {
                dist[j] = g[v][j];
            }
        }
    }
    return sum;
}
int main()
{
    memset(g, inf, sizeof g);
    cin >> n >> m;
    for(int i = 0;i < m;i++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        g[a][b] = g[b][a] = min(g[a][b], c);
    }
    int ans = prim();
    if(ans == inf)
    cout << "impossible";
    else
    cout << ans;
    return 0;
}


活动打卡代码 AcWing 854. Floyd求最短路

17865429953
6个月前
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 210;
const int inf = 0x3f3f3f3f;
int d[MAXN][MAXN];
int n, m, q;
void Floyd()
{
    for(int k = 1;k <= n;k++)
    {
        for(int i = 1;i <= n;i++)
        {
            for(int j = 1;j <= n;j++)
            {
                d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
            }
        }
    }
}
int main()
{
    //memset(d, inf, sizeof d);
    cin >> n >> m >> q;
    for(int i = 1;i <= n;i++)
    {
        for(int j = 1;j <= n;j++)
        {
            if(i == j)//到自己的距离是0 
            d[i][j] = 0;
            else
            d[i][j] = inf;
        }
     } 
    for(int i = 0;i < m;i++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        d[a][b] = min(d[a][b], c); 
    }
    Floyd();
    while(q--)
    {
        int a, b;
        cin >> a >> b;
        if(d[a][b] > inf / 2) 
        //因为存在负权边所以如果两个点之间没有通路  但这两个点的距离可能比inf小一些 
        {
            cout << "impossible" << endl;
        }
        else
        cout << d[a][b] << endl;
    }
    return 0;
 } 


活动打卡代码 AcWing 852. spfa判断负环

17865429953
6个月前
//①存在点入队的次数超过n-1就说明有负环
//②某条最短路径上的点的个数超过n就说明有环 
/*
存在着某一个源点不可达的负环  所以要让每一个点都充当源点才能看出图中是否存在负环 也即每个点当作源点执行一遍spfa()
但这样太慢会超时 !!!
可以这样想添加一个虚拟的点x,x到每个点都是可达的 且 边的权重是0  将x当作唯一源点 从x开始找负环 那么可定是可达的
dist[]表示其他所有点到x的最短路 
*/
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN = 2010;
const int MAXM = 10010;
int h[MAXM], e[MAXM], w[MAXM], ne[MAXM], idx;
int n, m;
bool st[MAXN];
int dist[MAXN], cnt[MAXN];
void add(int a, int b, int c)
{
    e[idx] = b;
    w[idx] = c;
    ne[idx] = h[a];
    h[a] = idx;
    idx++;
}

bool spfa()
{
    queue<int> q;
    for(int i = 1;i <= n;i++)
    {
        q.push(i);
        st[i] = true;
    }
    while(!q.empty())
    {
        int v = q.front();
        q.pop();
        st[v] = false;
        for(int i = h[v];i != -1;i = ne[i])
        {
            int nv = e[i];
            if(dist[nv] > dist[v] + w[i])
            {
                dist[nv] = dist[v] + w[i];
                cnt[nv] = cnt[v] + 1;
                if(cnt[nv] > n)
                {
                    return true; //有环 
                }
                if(!st[nv])
                {
                    q.push(nv);
                    st[nv] = true;
                }
            }
        }
    }
    return false; 
}
int main()
{
    memset(h, -1, sizeof h);
    cin >> n >> m;
    for(int i = 0;i < m;i++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        add(a, b, c);
    }

    if(spfa())
    cout << "Yes";
    else
    cout << "No";
    return 0;
}