通过建立糖果数变多的有向图来由拥有糖果数最少的那个人下手去计算出每个小朋友的最小糖果数。
那么在这里增加一个0点当做起点,然后可以从起点出发求出每个点的最小糖果数。
由于在这里我们差分的值就是最小值,所以我们要求尽量满足差分条件。
那么我们在寻找的时候就要去寻找最大值。这样可以让每一条边的条件都满足。
在本题当中比较坑的一点是不能使用queue去保存,会导致超时,其实按道理queu的操作不应该是O(1)的复杂度吗?咋会超时,不太理解。
本题只能用SPFA算法,不能使用Dijkstra算法。因为本题需要求最大的值,而最大值是在不断增大的。这不符合Dijkstra在使用过程中的贪心单调。
//通过建立糖果数变多的有向图来由拥有糖果数最少的那个人下手去计算出每个小朋友的最小糖果数。
//那么在这里增加一个0点当做起点,然后可以从起点出发求出每个点的最小糖果数。
//由于在这里我们差分的值就是最小值,所以我们要求尽量满足差分条件。
//那么我们在寻找的时候就要去寻找最大值。这样可以让每一条边的条件都满足。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 100000*3+30;
const int maxnn = 100000+10;
struct sy{
    int next;
    int to;
    int w;
} edge[maxn];
int head[maxn];
int cnt = 0;
int len[maxnn];
int num[maxnn];
int st[maxnn];
bool vis[maxnn];
int q[maxn];
int n, k;
struct Node{
    int number;
    int val;
    bool operator < (const Node &n) const 
    {
        return val<n.val;
    }
};
void add_edge(int x, int y, int w)
{
    edge[++cnt].next = head[x];
    edge[cnt].to = y;
    edge[cnt].w = w;
    head[x] = cnt;
}

bool Spfa()
{
    memset(len, -0x3f, sizeof(len));
//     queue<int> q;
//     q.push(0);
    int tt = 1;
    q[0] = 0;
    st[0] = true;
    len[0] = 0;
    while (tt)
    {
        int number = q[--tt];
        st[number] = false;
        num[number]++;
        if (num[number]>=n+1) return false;
        for (int i=head[number];i!=-1;i = edge[i].next)
        {
            int next = edge[i].to;
            int w = edge[i].w;
            if (len[number]+w>len[next])
            {
                len[next] = len[number]+w;
                
                if (st[next]==false)
                {
                    q[tt++] = next;
                    st[next] = true;
                }
            }
        }
    }
    return true;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    memset(head, -1, sizeof(head));
    int op, x, y;
    cin>>n>>k;
    while (k--)
    {
        cin>>op>>x>>y;
        switch (op) {
            case 1:
                add_edge(x, y, 0);
                add_edge(y, x, 0);
                break;
            case 2:
                add_edge(x, y, 1);
                break;
            case 3:
                add_edge(y, x, 0);
                break;
            case 4:
                add_edge(y, x, 1);
                break;
            case 5:
                add_edge(x, y, 0);
                break;
        }
    }
    //搞一个0点,作为起点去计算其他点的数值。
    for (int i=1;i<=n;i++) add_edge(0, i, 1);
    int bl = Spfa();
    if (!bl)
    {
        cout<<-1;
        return 0;
    }
    int ans = 0;
    for (int i=1;i<=n;i++)
    {
        if (len[i]<-1)
        {
            cout<<-1;
            return 0;
        }
        ans += len[i];
    }
    cout<<ans<<"\n";
    return 0;
}